This is the results section for the Study 2 NSE & SE CHILDREN watching ASL Stories. We have two main factors:

  1. Language (Sign v. English)
  2. Direction (Forward v. Reversed)

We are taking out one older KODA (Ethan, 10.5 yrs) to balance the groups better.

Demographics

library(tidyverse)
library(janitor)
library(lme4)
library(lmerTest)
library(scales)
library(feather)
library(GGally)
kids <- read_feather("cleanedchildeyedata.feather") %>%
#  mutate(age = age*12) %>%
  select(participant, language, age, gender, story, direction, mark, trial, repetition, aoi, secs, percent) %>%
  rename(name = participant) %>%
  filter(age < 9) %>% # Take out Ethan
  # mutate(agegroup = case_when(
  #   age <= 8.99 ~ "younger",
  #   age >= 9.0 & age < 15 ~ "older"
  # )) %>%
  # filter(!is.na(agegroup)) %>%
  mutate(language = case_when(
    language == "english" ~ "NSE",
    language =="sign" ~ "SE"
  )) %>%
  rename(lang = language)
kidsinfo <- kids %>%
  select(name, lang, age, gender) %>%
  distinct() %>%
  group_by(lang) %>%
  summarise(N = n(),
            age_mean = mean(age),
            sd = sd(age),
            min = min(age),
            max = max(age))
genders <- kids %>%
  select(name, lang, age, gender) %>%
  distinct() %>%
  group_by(lang, gender) %>%
  summarise(N = n()) %>%
  spread(gender, N)
kidsinfo <- left_join(kidsinfo, genders) %>%
  select(lang, N, Female, Male, age_mean, sd, min, max) %>%
  print()
# babies$agegroup <- fct_relevel(babies$agegroup, c("younger","older"))
# IF we do age groups, use this code
# 
# babiesinfo <- babies %>%
#   select(name, lang, age, agegroup, gender) %>%
#   distinct() %>%
#   group_by(lang, agegroup) %>%
#   summarise(N = n(),
#             age_mean = mean(age),
#             sd = sd(age),
#             min = min(age),
#             max = max(age))
# 
# genders <- babies %>%
#   select(name, lang, age, agegroup, gender) %>%
#   distinct() %>%
#   group_by(lang, agegroup, gender) %>%
#   summarise(N = n()) %>%
#   spread(gender, N)
# 
# babiesinfo <- left_join(babiesinfo, genders) %>%
#   select(lang, agegroup, N, Female, Male, age_mean, sd, min, max) %>%
#   print()

Let’s plot the ages, and check if there is significant difference in ages between the two groups?

# Boxplot
kids %>%
  select(name, age, lang) %>%
  distinct() %>%
  ggplot(aes(x = lang, y = age, fill = lang)) + geom_boxplot(width = 0.5) + guides(fill = FALSE)

kids %>%
  select(name, age, lang) %>%
  distinct() %>%
  ggplot(aes(x = age, fill = lang)) + geom_histogram() + facet_grid(lang ~ .)

# T-test
nse_age <- kids %>% filter(lang == "NSE") %>% select(name, age) %>% distinct()
se_age <- kids %>% filter(lang == "SE") %>% select(name, age) %>% distinct()
t.test(nse_age$age, se_age$age)

    Welch Two Sample t-test

data:  nse_age$age and se_age$age
t = 0.14316, df = 32.568, p-value = 0.887
alternative hypothesis: true difference in means is not equal to 0
95 percent confidence interval:
 -1.020020  1.174354
sample estimates:
mean of x mean of y 
 4.986667  4.909500 

Global Looking

For children, we calculated percentages based on overall clip length as the denominator. In this way, we can meaningfully contrast looking times at the videos (which are variable lengths) based on different factors. But when we go to AOI analysis we need to re-calculate the percentages so the denominator is based on total looking time, not overall clip length.

The chart below shows there seems to be an effect of age; older kids look longer at it than younger kids. Maybe not too surprising. It means we need to keep age in any models we run. Let’s analyze a bit more below.

kids$lang <- as.factor(kids$lang)
kids_overall_looking <- kids %>%
  group_by(name, age, lang, direction, story, repetition) %>%
  summarise(percent = sum(percent)) # gets total looking percent for each trial for each kid
# Table of means
kids_overall_looking %>% 
  group_by(name, lang, direction) %>%
  summarise(percent = mean(percent)) %>% # get average looking percent for each kid
  group_by(lang, direction) %>%
  summarise(mean_percent = mean(percent),
            count = n(),
            sd = sd(percent),
            se = sd/sqrt(count)) %>%
  select(-sd) %>%
  print()
ggplot(kids_overall_looking, aes(x = age, y = percent, color = direction, fill = direction)) + 
  geom_jitter(alpha = 0.5) +
  facet_grid(. ~ lang) +
  geom_smooth(method = "lm", se = TRUE) +
  ggtitle("Video Attention") +
  xlab("age (months)") +
  ylab("percent looking") + 
  theme_bw() + 
  scale_y_continuous(limits = c(0,1), labels = percent) 

# Plot
# babies_overall_looking %>% 
#   group_by(lang, direction, name) %>%
#   summarise(percent = mean(percent)) %>% # gets average looking percent for each baby
#   group_by(lang, direction) %>%
#   summarise(mean_percent = mean(percent), # gets group averages
#             count = n(),
#             sd = sd(percent),
#             se = sd/sqrt(count)) %>% 
#   ggplot(aes(x = lang, y = mean_percent, fill = direction)) + 
#   geom_col(position = "dodge") + 
#   geom_errorbar(aes(ymin = mean_percent - se, ymax = mean_percent + se), 
#                 position = position_dodge(width = 0.9), width = 0.25) + 
#   scale_y_continuous(limits = c(0,1), labels = percent) +
#   theme_minimal() + 
#   theme(panel.grid.major.x = element_blank()) +
# #  facet_wrap("lang") +
#   ggtitle("Video Attention") +
#   xlab("") +
#   ylab("percent looking")
# babies_overall_looking %>%
#   ggplot(aes(x = lang, y = percent, fill = direction)) +
#   facet_wrap("agegroup") + 
#   geom_violin()

A linear model shows a significant effect of age. Overall, Age seems to increase overall looking by about 3% every year. However, there are no differences between NSE v. SE, or reversal, on how long they looked, so that’s good.

global_lm <- lmer(percent ~ age + lang * direction + (1|name) + (1|story), data = kids_overall_looking)
summary(global_lm)
Linear mixed model fit by REML. t-tests use Satterthwaite's method ['lmerModLmerTest']
Formula: percent ~ age + lang * direction + (1 | name) + (1 | story)
   Data: kids_overall_looking

REML criterion at convergence: -112.3

Scaled residuals: 
    Min      1Q  Median      3Q     Max 
-2.4984 -0.6942  0.2184  0.7802  2.5040 

Random effects:
 Groups   Name        Variance  Std.Dev.
 name     (Intercept) 0.0071099 0.08432 
 story    (Intercept) 0.0003724 0.01930 
 Residual             0.0397616 0.19940 
Number of obs: 471, groups:  name, 35; story, 8

Fixed effects:
                           Estimate Std. Error         df t value Pr(>|t|)    
(Intercept)                0.582022   0.062000  34.960192   9.387 4.37e-11 ***
age                        0.032069   0.010836  30.900877   2.959  0.00587 ** 
langSE                     0.032270   0.039171  51.078694   0.824  0.41386    
directionreversed         -0.031150   0.028318 375.529039  -1.100  0.27203    
langSE:directionreversed  -0.003912   0.037809 384.535230  -0.103  0.91765    
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Correlation of Fixed Effects:
            (Intr) age    langSE drctnr
age         -0.872                     
langSE      -0.376  0.019              
dirctnrvrsd -0.234  0.004  0.368       
lngSE:drctn  0.179 -0.006 -0.482 -0.756
#ggcoef(global_lm)

AOI Looking

Now we’ll re-calculate the percentages so the denominator is based on total looking time. All AOIs should sum up to 100% for each trial and each baby. Next let’s make a boxplot of all AOIs. Interesting, definitely more MidFaceBottom focus here than we had with babies, but also more distribution too.

# Recalculate percent
kids <- kids %>% 
  select(-percent) %>%
  group_by(name, lang, age, direction, story, mark, trial, repetition) %>%
  mutate(totalsec = sum(secs)) %>%
  group_by(name, lang, age, direction, story, mark, trial, repetition, aoi) %>%
  summarise(percent = secs/totalsec)
# Boxplot
kids %>%
  ggplot(aes(x = aoi, y = percent, fill = direction)) + 
  geom_boxplot() +
  ggtitle("AOI Attention") +
  theme_bw() + 
  xlab("") +
  theme(axis.text.x = element_text(angle=45, hjust = 1),
        panel.grid.major.x = element_blank()) +
  scale_y_continuous(labels = scales::percent, limits = c(0,1))

It appears two important AOIs are MidChestTop and MidFaceBottom. Let’s look again only at midline AOIs:

midline = c("Belly","BelowChest","MidChestBottom","MidChestCenter","MidChestTop",
            "MidFaceBottom","MidFaceCenter","MidFaceTop")
kids %>%
  filter(aoi %in% midline) %>%
  ggplot(aes(x = aoi, y = percent, fill = direction)) + 
  geom_boxplot() +
  ggtitle("Midline AOI Attention") +
  theme_bw() + 
  xlab("") +
  theme(axis.text.x = element_text(angle=45, hjust = 1),
        panel.grid.major.x = element_blank()) +
  scale_y_continuous(labels = scales::percent, limits = c(0,1))

I’m going to run linear models with only MidChestTop or MidFaceBottom, and see what happens. No age interactions.

MidChestTop:

  • No effect of age.
  • No effect of language.
  • Weak effect of direction (p = 0.084) - reversed means they look ~ 4.7% less at midchesttop.
  • No language X direction interaction.

MidFaceBottom:

  • No effect of age.
  • Significant effect of language (p = 0.004) - SE look at MidFaceBottom +19% more than NSE children
  • No effect of direction.
  • No language X direction interaction.
kids %>%
  filter(aoi %in% c("MidFaceBottom","MidChestTop")) %>%
  ggplot(aes(x = age, y = percent, color = direction, fill = direction)) + 
  geom_jitter(alpha = 0.5) + 
  geom_smooth(method = "lm", se = FALSE) +
  scale_y_continuous(limits = c(0,1), labels = percent) +
  theme_bw() + 
#  theme(panel.grid.major.x = element_blank()) +
  facet_grid(aoi ~ lang) +
  ggtitle("AOI Attention") +
  xlab("") +
  ylab("percent looking")

midchesttop_lm <- lmer(percent ~ age + lang * direction + (1|name) + (1|story), data = filter(kids, aoi == "MidChestTop"))
summary(midchesttop_lm)
Linear mixed model fit by REML. t-tests use Satterthwaite's method ['lmerModLmerTest']
Formula: percent ~ age + lang * direction + (1 | name) + (1 | story)
   Data: filter(kids, aoi == "MidChestTop")

REML criterion at convergence: -108

Scaled residuals: 
    Min      1Q  Median      3Q     Max 
-2.0759 -0.6139 -0.1635  0.5257  3.4431 

Random effects:
 Groups   Name        Variance  Std.Dev.
 name     (Intercept) 0.0236538 0.15380 
 story    (Intercept) 0.0001076 0.01037 
 Residual             0.0375729 0.19384 
Number of obs: 471, groups:  name, 35; story, 8

Fixed effects:
                           Estimate Std. Error         df t value Pr(>|t|)   
(Intercept)                0.332735   0.097931  33.690951   3.398  0.00176 **
age                       -0.004869   0.017507  32.325737  -0.278  0.78269   
langSE                    -0.067047   0.058495  39.321521  -1.146  0.25863   
directionreversed         -0.047327   0.027264 337.964771  -1.736  0.08350 . 
langSE:directionreversed   0.049457   0.036436 348.960799   1.357  0.17554   
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Correlation of Fixed Effects:
            (Intr) age    langSE drctnr
age         -0.892                     
langSE      -0.360  0.022              
dirctnrvrsd -0.142  0.003  0.235       
lngSE:drctn  0.109 -0.004 -0.310 -0.751
#ggcoef(midchesttop_lm)
midfacebottom_lm <- lmer(percent ~ age + lang * direction + (1|name) + (1|story), data = filter(kids, aoi == "MidFaceBottom"))
summary(midfacebottom_lm)
Linear mixed model fit by REML. t-tests use Satterthwaite's method ['lmerModLmerTest']
Formula: percent ~ age + lang * direction + (1 | name) + (1 | story)
   Data: filter(kids, aoi == "MidFaceBottom")

REML criterion at convergence: 27

Scaled residuals: 
    Min      1Q  Median      3Q     Max 
-2.6917 -0.6530 -0.0125  0.7073  2.5459 

Random effects:
 Groups   Name        Variance Std.Dev.
 name     (Intercept) 0.025608 0.16003 
 story    (Intercept) 0.001334 0.03652 
 Residual             0.050261 0.22419 
Number of obs: 471, groups:  name, 35; story, 8

Fixed effects:
                           Estimate Std. Error         df t value Pr(>|t|)   
(Intercept)                0.359107   0.104202  34.707523   3.446  0.00151 **
age                       -0.005518   0.018451  32.184210  -0.299  0.76684   
langSE                     0.188369   0.062415  41.101136   3.018  0.00436 **
directionreversed         -0.005451   0.032290 418.172403  -0.169  0.86602   
langSE:directionreversed  -0.049417   0.043090 421.681027  -1.147  0.25210   
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Correlation of Fixed Effects:
            (Intr) age    langSE drctnr
age         -0.883                     
langSE      -0.361  0.021              
dirctnrvrsd -0.158  0.002  0.266       
lngSE:drctn  0.122 -0.003 -0.345 -0.762
#ggcoef(midfacebottom_lm)
# Bar chart
# babies %>%
#   filter(aoi %in% c("MidFaceBottom","MidChestTop")) %>%
#   group_by(agegroup, lang, direction, name, aoi) %>%
#   summarise(percent = mean(percent)) %>% # gets average looking percent for each baby
#   group_by(agegroup, lang, direction, aoi) %>%
#   summarise(mean_percent = mean(percent), # gets group averages
#             count = n(),
#             sd = sd(percent),
#             se = sd/sqrt(count)) %>% 
#   ggplot(aes(x = lang, y = mean_percent, fill = direction)) + 
#   geom_col(position = "dodge") + 
#   geom_errorbar(aes(ymin = mean_percent - se, ymax = mean_percent + se), 
#                 position = position_dodge(width = 0.9), width = 0.25) + 
#   scale_y_continuous(limits = c(0,1), labels = percent) +
#   theme_minimal() + 
#   theme(panel.grid.major.x = element_blank()) +
#   facet_grid(aoi ~ agegroup) +
#   ggtitle("Video Attention") +
#   xlab("") +
#   ylab("percent looking")

Face-Chest Ratio

Next, we’ll define a Face-Chest Ratio (FCR) such that:

  1. MidFaceCenter, MidFaceBottom = Face
  2. MidChestTop, MidChestCenter, MidChestBottom, BelowChest = Chest
  3. FCR = face - chest / face + chest

We did not include Belly or MidFaceTop because of very low looking rates according to the boxplots above.

kids_fcr <- kids %>%
  spread(aoi,percent) %>%
  group_by(name, age, lang, direction, story, repetition) %>%
  summarise(face = sum(MidFaceCenter, MidFaceBottom, na.rm = TRUE),
         chest = sum(MidChestTop, MidChestCenter, MidChestBottom, BelowChest, na.rm = TRUE),
         fcr = (face - chest) / (face + chest))
# Table of means
kids_fcr %>% 
  group_by(lang, direction, name) %>%
  summarise(fcr = mean(fcr)) %>% # gets average looking percent for each baby
  group_by(lang, direction) %>%
  summarise(mean_fcr = mean(fcr), # gets group averages
            count = n(),
            sd = sd(fcr),
            se = sd/sqrt(count)) %>%
  select(-sd) %>%
  print()
# Plot
ggplot(kids_fcr, aes(x = age, y = fcr, color = direction, fill = direction)) + 
  geom_hline(yintercept = 0, linetype = "dashed") +
  geom_jitter(alpha = 0.5) + 
  geom_smooth(method = "lm", se = FALSE) +
  scale_y_continuous(limits = c(-1,1)) +
  theme_bw() + 
  theme(panel.grid.major.x = element_blank()) +
  facet_grid(. ~ lang) +
  ggtitle("Face-Chest Ratios") +
  xlab("") +
  ylab("FCR")

# Bar chart
# babies_fcr %>% 
#   group_by(agegroup, lang, direction, name) %>%
#   summarise(fcr = mean(fcr)) %>% # gets average looking percent for each baby
#   group_by(agegroup, lang, direction) %>%
#   summarise(mean_fcr = mean(fcr), # gets group averages
#             count = n(),
#             sd = sd(fcr),
#             se = sd/sqrt(count)) %>% 
#   ggplot(aes(x = lang, y = mean_fcr, fill = direction)) + 
#   geom_col(position = "dodge") + 
#   geom_errorbar(aes(ymin = mean_fcr - se, ymax = mean_fcr + se), 
#                 position = position_dodge(width = 0.9), width = 0.25) + 
#   scale_y_continuous(limits = c(-1,1)) +
#   theme_minimal() + 
#   theme(panel.grid.major.x = element_blank()) +
#   facet_wrap("agegroup") +
#   ggtitle("Face-Chest Ratios") +
#   xlab("") +
#   ylab("FCR")

What will a linear mixed model tell us? (with no age interactions)

  • No effect of age. Interesting. Maybe just becuase we don’t have that many babies.
  • Effect of language: SE babies have overall +0.36 FCR than NSE babies (p = 0.03). SE looks at the face more than the chest.
  • No effect of direction. Interesting.
  • No interaction. Interesting.
fcr_lm <- lmer(fcr ~ age + lang * direction + (1|name) + (1|story), data = kids_fcr)
summary(fcr_lm)
Linear mixed model fit by REML. t-tests use Satterthwaite's method ['lmerModLmerTest']
Formula: fcr ~ age + lang * direction + (1 | name) + (1 | story)
   Data: kids_fcr

REML criterion at convergence: 747.9

Scaled residuals: 
     Min       1Q   Median       3Q      Max 
-3.04087 -0.55798  0.04156  0.68150  2.93235 

Random effects:
 Groups   Name        Variance Std.Dev.
 name     (Intercept) 0.17809  0.4220  
 story    (Intercept) 0.01392  0.1180  
 Residual             0.22797  0.4775  
Number of obs: 471, groups:  name, 35; story, 8

Fixed effects:
                           Estimate Std. Error         df t value Pr(>|t|)  
(Intercept)               -0.051211   0.268645  34.803179  -0.191   0.8499  
age                       -0.001861   0.047533  32.187271  -0.039   0.9690  
langSE                     0.357443   0.157942  38.316970   2.263   0.0294 *
directionreversed         -0.047553   0.069424 433.299141  -0.685   0.4937  
langSE:directionreversed  -0.068533   0.092601 434.179175  -0.740   0.4596  
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Correlation of Fixed Effects:
            (Intr) age    langSE drctnr
age         -0.882                     
langSE      -0.355  0.022              
dirctnrvrsd -0.132  0.001  0.227       
lngSE:drctn  0.102 -0.002 -0.293 -0.766
#ggcoef(fcr_lm)

Visualizing Reversal Effect

I want to try to visualize reversal effects a different way. Maybe this.

# Get participant-level data
kids_fcr2 <- kids_fcr %>%
  group_by(name, age, lang, direction) %>%
  summarise(fcr = mean(fcr))
# reversal_effect_lm <- lmer(fcr ~ age + lang * direction + (1|name), data = kids_fcr2)
# summary(reversal_effect_lm)
ggplot(kids_fcr2, aes(x = direction, y = fcr, color = lang, fill = lang)) +
  geom_point() +
  geom_line(aes(group = name)) +
  facet_grid(. ~ lang) + 
  scale_y_continuous(limits = c(-1,1)) +
  theme_bw()

Or a reversal effect chart? Okay, so this chart tells us overall there really wasn’t much of a reversal effect for SE babies, they’re all hovering around 0. Interesting. While there seems to be a reversal effect for NSE babies where they look at the face more during reversed stories!

# Get participant-level data
kids_fcr3 <- kids_fcr2 %>%
  spread(direction, fcr) %>%
  group_by(name, age, lang) %>%
  summarise(diff = forward - reversed)
ggplot(kids_fcr3, aes(x = age, y = diff, color = lang)) +
  geom_point() +
  geom_smooth(method = "lm", se = FALSE) +
  scale_y_continuous(limits = c(-1,1)) +
  theme_bw() +
  ggtitle("Reversal Effect") +
  ylab("Forward FCR - Reversed FCR")

And within-subjects variation here:

# First get the mean of each trial, THEN the participant-level means
within_subjects <- kids_fcr %>%
  group_by(name, lang, direction, story, repetition) %>%
  summarise(fcr = mean(fcr, na.rm = TRUE),
            count = n()) %>%
  group_by(name, lang, direction) %>%
  summarise(mean = mean(fcr, na.rm = TRUE),
            se = sd(fcr, na.rm = TRUE)/sqrt(n()),
            count = n())
# Then spread out mean and SE columns by direction
within_subjects_means <- within_subjects %>%
  select(-se, -count) %>%
  spread(direction, mean, sep = "_")
within_subjects_se <- within_subjects %>%
  select(-mean, -count) %>%
  spread(direction, se, sep = "SE")
within_subjects <- left_join(within_subjects_means, within_subjects_se, by = c("name","lang"))
# Now let's plot
lims <- c(-1,1)
within_subjects %>%
  ggplot(aes(x = direction_forward, y = direction_reversed, color = lang)) +
    geom_abline() +
  geom_point(size = 2) + 
  geom_errorbar(aes(ymin=direction_reversed-directionSEreversed, ymax=direction_reversed+directionSEreversed)) +
  geom_errorbarh(aes(xmin=direction_forward-directionSEforward, xmax=direction_forward+directionSEforward)) +
  theme_bw() +
  theme(aspect.ratio = 1) +
  scale_x_continuous("forward", limits = c(-1,1)) +
  scale_y_continuous("reversed", limits = c(-1,1)) +
  ggtitle("FCR Means") +
  facet_wrap("lang")

And a classic box/error plot with age collapsed.

kids_fcr2 %>%
  group_by(lang, direction) %>%
  summarise(fcr_mean = mean(fcr),
            sd = sd(fcr),
            n = n(),
            se = sd/sqrt(n)) %>%
  ggplot(aes(x = lang, y = fcr_mean, fill = direction)) +
  geom_bar(stat = "identity", position = position_dodge()) + 
  geom_errorbar(aes(ymin = fcr_mean-se, ymax = fcr_mean+se), position = position_dodge(0.9), width = 0.2) +
  scale_y_continuous(limits = c(-0.5, 0.5)) +
  theme_linedraw()

library(extrafont)
Registering fonts with R
kids_fcr2 %>%
  group_by(lang, direction) %>%
  summarise(fcr_mean = mean(fcr),
            sd = sd(fcr),
            n = n(),
            se = sd/sqrt(n)) %>%
  ggplot(aes(x = lang, y = fcr_mean, color = direction, fill = direction, group = direction)) +
  geom_hline(yintercept = 0, size = 0.5) +
  geom_point(size = 6, position = position_dodge(width = 0.4)) +
  geom_errorbar(aes(ymin = fcr_mean-se, ymax = fcr_mean+se), 
                size = 2, 
                position = position_dodge(0.4), 
                width = 0.3) +
  scale_y_continuous(limits = c(-0.5, 0.5)) +
  theme_linedraw() +
  theme(text = element_text(size = 30, family = "xkcd"),
        panel.grid.minor.y = element_blank(),
        panel.grid.major.x = element_blank(),
        axis.title.y = element_blank(),
        axis.title.x = element_blank(),
        axis.text.x = element_blank(),
        axis.ticks.x = element_blank(),
        panel.border = element_rect(size = 2),
        axis.ticks.y = element_line(size = 0.5),
        panel.grid.major.y = element_line(size = 0.5, color = "light gray", linetype = "dashed")) +
  guides(color = FALSE, fill = FALSE)

Heat Maps

And now heat maps!

heatmap_kids <- kids %>%
  filter(aoi %in% midline) %>%
  ungroup() %>%
  group_by(lang, name, direction, aoi) %>%
  summarise(percent = mean(percent, na.rm=TRUE)) %>%
  group_by(lang, direction, aoi) %>%
  summarise(percent = mean(percent, na.rm=TRUE)) %>%
  ungroup() %>%
  mutate(aoi = factor(aoi, levels = c("Belly","BelowChest","MidChestBottom","MidChestCenter","MidChestTop",
            "MidFaceBottom","MidFaceCenter","MidFaceTop")))
ggplot(heatmap_kids, aes(x = lang, y = aoi)) +
  geom_tile(aes(fill=percent),color="lightgray",na.rm=TRUE) + 
#  scale_fill_viridis(option = "viridis", direction=-1, limits = c(0,.7), labels = percent, name = "looking time") +
    scale_fill_gradient(low = "#ffffff", high = "#08519c", space = "Lab", limits = c(0,.52), labels = percent, name = "looking time", na.value = "grey50") +
  theme_bw() +
  theme(strip.text.x = element_text(size = 11, color = "black", face = "italic"), 
        strip.background = element_rect(colour = "white", fill = "white"),
        panel.grid.major = element_line(color = "white")) +
  facet_grid(. ~ direction) +
  ylab("") + xlab("") + ggtitle("Eye Gaze Heat Map, by Direction") + 
  scale_y_discrete(expand=c(0,0)) +
  scale_x_discrete(expand = c(0,0))

ggplot(heatmap_kids, aes(x = direction, y = aoi)) +
  geom_tile(aes(fill=percent),color="lightgray",na.rm=TRUE) + 
#  scale_fill_viridis(option = "viridis", direction=-1, limits = c(0,.7), labels = percent, name = "looking time") +
    scale_fill_gradient(low = "#ffffff", high = "#08519c", space = "Lab", limits = c(0,.52), labels = percent, name = "looking time", na.value = "grey50") +
  theme_bw() +
  theme(strip.text.x = element_text(size = 11, color = "black", face = "italic"), 
        strip.background = element_rect(colour = "white", fill = "white"),
        panel.grid.major = element_line(color = "white")) +
  facet_grid(. ~ lang) +
  ylab("") + xlab("") + ggtitle("Eye Gaze Heat Map, by Language") + 
  scale_y_discrete(expand=c(0,0)) +
  scale_x_discrete(expand = c(0,0))

# All Data
#Here's all AOI data. 
kids %>%
  ungroup() %>%
  group_by(lang, name, direction, aoi) %>%
  summarise(percent = mean(percent, na.rm=TRUE)) %>%
  group_by(lang, direction, aoi) %>%
  summarise(percent = mean(percent, na.rm=TRUE)) %>%
  openxlsx::write.xlsx("~/Desktop/kids_by_direction.xlsx")
kids %>%
  ungroup() %>%
  group_by(lang, name, direction, aoi) %>%
  summarise(percent = mean(percent, na.rm=TRUE)) %>%
  group_by(lang, direction, aoi) %>%
  summarise(percent = mean(percent, na.rm=TRUE)) %>%
  group_by(lang, aoi) %>%
  summarise(percent = mean(percent, na.rm=TRUE)) %>%
  openxlsx::write.xlsx("~/Desktop/kids_collapsed.xlsx")

Discussion

No big changes from the ICSLA abstract. Good!

The interpretation here is that:

  • All kids looked equally at all videos regardless of language or direction. Age did have an effect so we used age in our models. Good!
  • SE kids continue to be strong face-lookers compared to NSE kids. (Same as ICSLA)
  • There is no reversal effect. (Same as ICSLA)

That doesn’t mean both groups of children don’t care about reversal. On the contrary. We can hypothesize that SE kids have efficient gaze behavior and are resilient to reversal; while NSE kids already are “inefficient” and changing the video stimulus isn’t going to help. But how do we test that? Maybe let’s look at within-subject variation.

Correlations

Let’s try correlations.

# Let's try correlations
kids_nse <- kids %>% 
  filter(aoi %in% midline) %>%
  filter(lang == "NSE") %>%
  group_by(name, direction, aoi) %>% 
  summarise(percent = mean(percent)) %>%
  ungroup() %>%
  mutate(direction = case_when(
    direction == "forward" ~ "fw",
    direction == "reversed" ~ "rv"
  )) %>% 
  unite(aoi2, direction, aoi, sep = "_") %>%
  spread(aoi2, percent) %>%
  select(-name)
kids_se <- kids %>% 
  filter(aoi %in% midline) %>%
  filter(lang == "SE") %>%
  group_by(name, direction, aoi) %>% 
  summarise(percent = mean(percent)) %>%
  ungroup() %>%
  mutate(direction = case_when(
    direction == "forward" ~ "fw",
    direction == "reversed" ~ "rv"
  )) %>% 
  unite(aoi2, direction, aoi, sep = "_") %>%
  spread(aoi2, percent) %>%
  select(-name)
ggcorr(kids_nse, label = TRUE, label_size = 5, label_round = 2, label_alpha = TRUE, hjust = 0.9, size = 5, color = "grey50", layout.exp = 1) + ggtitle("NSE")

ggcorr(kids_se, label = TRUE, label_size = 5, label_round = 2, label_alpha = TRUE, hjust = 0.9, size = 5, color = "grey50", layout.exp = 1) + ggtitle("SE")

library(corrr)
kids_nse %>% correlate() %>% network_plot(min_cor=0.6) + ggtitle("NSE Children")

kids_se %>% correlate() %>% network_plot(min_cor=0.6) + ggtitle("SE Children")

XY Space Data

We’ll load the data from the childxydata.feather file made in 06rawxydata.Rmd. So any new kids, please run the first code block in 06 to include it. Then we’ll keep all the kids we also have in the AOI data group.

included <- kids %>%
  ungroup() %>%
  select(name) %>% 
  distinct() %>%
  unlist()
xydata <- read_feather("../Child Data/childxydata.feather") %>%
  rename(name = participant) %>%
  filter(name %in% included)
# Get ages
ages <- read_csv("childrenages.csv") %>%
  rename(name = participant)
xydata <- xydata %>% left_join(ages, by = "name") %>%
  mutate(age = age*12) %>%
  mutate(agegroup = case_when(
    age <= 8.99 ~ "younger",
    age >= 9.0 & age < 15 ~ "older"
  )) %>%
  mutate(language = case_when(
    language == "EnglishExposed" ~ "NSE",
    language == "SignLanguageExposed" ~ "SE"
  )) %>%
  rename(lang = language) %>%
  select(name, group, gender, lang, condition, mark, trial, repetition, x, y, age, agegroup) %>%
  separate(condition, into = c("story", "clip", "direction")) %>%
  unite("story", c("story", "clip")) %>%
  mutate(direction = case_when(
    direction == "ER" ~ "reversed",
    direction == "FW" ~ "forward"
  )) %>%
  mutate(name = factor(name),
         group = factor(group),
         gender = factor(gender),
         lang = factor(lang),
         story = factor(story),
         direction = factor(direction),
         mark = factor(mark),
         trial = factor(trial),
         repetition = factor(repetition),
         agegroup = factor(agegroup))

Overall Looking

Let’s check that we have no significant group or condition differences in terms of valid (not empty) data points collected. This is same as “Global Looking” we have above, really, but w raw xy data.

xy_overall <- xydata %>%
  filter(!is.na(x)) %>%
  group_by(name, age, lang, direction, story, repetition) %>%
  summarise(data_points = n()) # gets total looking percent for each trial for each baby
# Table of means
xy_overall %>% 
  group_by(name, lang, direction) %>%
  summarise(data_points = mean(data_points)) %>% # get average looking percent for each baby
  group_by(lang, direction) %>%
  summarise(mean_data_points = mean(data_points),
            count = n(),
            sd = sd(data_points),
            se = sd/sqrt(count)) %>%
  select(-sd) %>%
  print()
ggplot(xy_overall, aes(x = age, y = data_points, color = direction, fill = direction)) + 
  geom_jitter(alpha = 0.5) +
  facet_grid(. ~ lang) +
  geom_smooth(method = "lm", se = FALSE) +
  ggtitle("Data Points") +
  xlab("age (months)") +
  ylab("data points recorded") + 
  theme_bw() 

Description.

overall_xy_lm <- lmer(data_points ~ age + lang * direction + (direction|name) + (direction|story), data = xy_overall)
summary(overall_xy_lm) 
Linear mixed model fit by REML. t-tests use Satterthwaite's method ['lmerModLmerTest']
Formula: data_points ~ age + lang * direction + (direction | name) + (direction |      story)
   Data: xy_overall

REML criterion at convergence: 7516.2

Scaled residuals: 
    Min      1Q  Median      3Q     Max 
-3.0141 -0.5798  0.1909  0.7325  2.2753 

Random effects:
 Groups   Name              Variance  Std.Dev. Corr 
 name     (Intercept)       1.896e+04 137.6804      
          directionreversed 5.468e-02   0.2338 1.00 
 story    (Intercept)       4.170e+04 204.1974      
          directionreversed 9.717e+03  98.5770 -0.44
 Residual                   6.768e+04 260.1533      
Number of obs: 535, groups:  name, 35; story, 8

Fixed effects:
                         Estimate Std. Error      df t value Pr(>|t|)    
(Intercept)               525.457    117.894  29.272   4.457 0.000112 ***
age                         2.465      1.397  32.977   1.765 0.086892 .  
langSE                      5.896     57.877  32.089   0.102 0.919493    
directionreversed         -17.944     49.949  12.211  -0.359 0.725547    
langSE:directionreversed   10.156     47.247 487.661   0.215 0.829889    
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Correlation of Fixed Effects:
            (Intr) age    langSE drctnr
age         -0.697                     
langSE      -0.278 -0.009              
dirctnrvrsd -0.297 -0.002  0.227       
lngSE:drctn  0.114  0.005 -0.406 -0.552
#ggcoef(overall_xy_lm)

XY Data LMMs

Now we’re going to run LMMs on babies’ raw:

  • horizontal spread (middle 50% of x data; xIQR)
  • vertical spread (middle 50% of y data; yIQR)
  • viewing area (A = middle-x * middle-y; area)

But to do this we first trim each kid’s data, getting rid of the first 60 samples (0.50 secs) of each trial.

xydata <- xydata %>%
  group_by(name,trial) %>%
  slice(30:n())
iqr <- xydata %>%
  group_by(name, age, lang, story, direction, trial) %>%
  summarise(xIQR = IQR(x,na.rm=TRUE),
                   yIQR = IQR(y,na.rm=TRUE),
                   xmed = median(x, na.rm=TRUE),
                   ymed = median(y, na.rm=TRUE),
                   area = xIQR*yIQR)
head(iqr,20)

Middle X

Description.

xiqr_mean <- iqr %>% 
  group_by(lang, direction, name) %>%
  summarise(xIQR = mean(xIQR, na.rm = T)) %>% # gets average looking percent for each baby
  group_by(lang, direction) %>%
  summarise(mean_xIQR = mean(xIQR), # gets group averages
            count = n(),
            sd = sd(xIQR),
            se = sd/sqrt(count)) %>%
  select(-sd) %>%
  print()
# Plot
ggplot(iqr, aes(x = age, y = xIQR, color = direction, fill = direction)) + 
  geom_jitter(alpha = 0.5) + 
  geom_smooth(method = "lm", se = FALSE) +
  theme_bw() + 
  theme(panel.grid.major.x = element_blank()) +
  facet_grid(. ~ lang) +
  ggtitle("Horizontal Spread") +
  xlab("") +
  ylab("xIQR")

ggplot(xiqr_mean, aes(x = lang, y = mean_xIQR, fill = direction)) +
  geom_bar(stat = "identity", position = position_dodge()) + 
  geom_errorbar(aes(ymin = mean_xIQR-se, ymax = mean_xIQR+se), position = position_dodge(0.9), width = 0.2) +
  theme_linedraw()

xiqr_lm <- lmer(xIQR ~ age + lang * direction + (1|name) + (1|story), data = iqr)
summary(xiqr_lm)
Linear mixed model fit by REML. t-tests use Satterthwaite's method ['lmerModLmerTest']
Formula: xIQR ~ age + lang * direction + (1 | name) + (1 | story)
   Data: iqr

REML criterion at convergence: 5145.4

Scaled residuals: 
    Min      1Q  Median      3Q     Max 
-1.3232 -0.4314 -0.1666  0.1539 12.5401 

Random effects:
 Groups   Name        Variance Std.Dev.
 name     (Intercept)  62.388   7.899  
 story    (Intercept)   8.698   2.949  
 Residual             878.268  29.636  
Number of obs: 534, groups:  name, 35; story, 8

Fixed effects:
                          Estimate Std. Error        df t value Pr(>|t|)    
(Intercept)               37.50826    6.90369  39.33107   5.433  3.1e-06 ***
age                       -0.05562    0.09857  32.45361  -0.564    0.576    
langSE                    -0.93298    4.55974  69.15306  -0.205    0.838    
directionreversed          3.17802    3.95955 434.71975   0.803    0.423    
langSE:directionreversed  -2.66564    5.25874 457.71103  -0.507    0.612    
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Correlation of Fixed Effects:
            (Intr) age    langSE drctnr
age         -0.853                     
langSE      -0.389  0.012              
dirctnrvrsd -0.287 -0.002  0.439       
lngSE:drctn  0.212  0.007 -0.572 -0.759
#ggcoef(xiqr_lm)

Middle Y

Description.

yiqr_mean <- iqr %>% 
  group_by(lang, direction, name) %>%
  summarise(yIQR = mean(yIQR, na.rm = T)) %>% # gets average looking percent for each baby
  group_by(lang, direction) %>%
  summarise(mean_yIQR = mean(yIQR), # gets group averages
            count = n(),
            sd = sd(yIQR),
            se = sd/sqrt(count)) %>%
  select(-sd) %>%
  print()
# Plot
ggplot(iqr, aes(x = age, y = yIQR, color = direction, fill = direction)) + 
  geom_jitter(alpha = 0.5) + 
  geom_smooth(method = "lm", se = FALSE) +
  theme_bw() + 
  theme(panel.grid.major.x = element_blank()) +
  facet_grid(. ~ lang) +
  ggtitle("Vertical Spread") +
  xlab("") +
  ylab("yIQR")

ggplot(yiqr_mean, aes(x = lang, y = mean_yIQR, fill = direction)) +
  geom_bar(stat = "identity", position = position_dodge()) + 
  geom_errorbar(aes(ymin = mean_yIQR-se, ymax = mean_yIQR+se), position = position_dodge(0.9), width = 0.2) +
  theme_linedraw()

yiqr_lm <- lmer(yIQR ~ age + lang * direction + (1|name) + (1|story), data = iqr)
summary(yiqr_lm)
Linear mixed model fit by REML. t-tests use Satterthwaite's method ['lmerModLmerTest']
Formula: yIQR ~ age + lang * direction + (1 | name) + (1 | story)
   Data: iqr

REML criterion at convergence: 5653.8

Scaled residuals: 
    Min      1Q  Median      3Q     Max 
-1.5596 -0.5064 -0.2414  0.1097  5.9864 

Random effects:
 Groups   Name        Variance Std.Dev.
 name     (Intercept)  300.671 17.340  
 story    (Intercept)    9.835  3.136  
 Residual             2251.601 47.451  
Number of obs: 534, groups:  name, 35; story, 8

Fixed effects:
                         Estimate Std. Error       df t value Pr(>|t|)    
(Intercept)               59.0444    13.0515  37.0017   4.524 6.07e-05 ***
age                       -0.1151     0.1903  32.8125  -0.605   0.5493    
langSE                   -10.5298     8.3370  56.5536  -1.263   0.2118    
directionreversed         10.9449     6.2896 400.3400   1.740   0.0826 .  
langSE:directionreversed -10.0338     8.3652 432.0794  -1.199   0.2310    
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Correlation of Fixed Effects:
            (Intr) age    langSE drctnr
age         -0.872                     
langSE      -0.378  0.015              
dirctnrvrsd -0.241 -0.001  0.381       
lngSE:drctn  0.178  0.006 -0.497 -0.755
#ggcoef(yiqr_lm)

Viewing Area

Description.

area_mean <- iqr %>% 
  group_by(lang, direction, name) %>%
  summarise(area = mean(area, na.rm = T)) %>% # gets average looking percent for each baby
  group_by(lang, direction) %>%
  summarise(area_mean = mean(area), # gets group averages
            count = n(),
            sd = sd(area),
            se = sd/sqrt(count)) %>%
  select(-sd) %>%
  print()
# Plot
ggplot(iqr, aes(x = age, y = area, color = direction, fill = direction)) + 
  geom_jitter(alpha = 0.5) + 
  geom_smooth(method = "lm", se = FALSE) +
  theme_bw() + 
  theme(panel.grid.major.x = element_blank()) +
  facet_grid(. ~ lang) +
  ggtitle("Viewing Area") +
  xlab("") +
  ylab("Area (px^2)")

ggplot(area_mean, aes(x = lang, y = area_mean, fill = direction)) +
  geom_bar(stat = "identity", position = position_dodge()) + 
  geom_errorbar(aes(ymin = area_mean-se, ymax = area_mean+se), position = position_dodge(0.9), width = 0.2) +
  theme_linedraw()

area_lm <- lmer(area ~ age + lang * direction + (1|name) + (1|story), data = iqr)
summary(area_lm)
Linear mixed model fit by REML. t-tests use Satterthwaite's method ['lmerModLmerTest']
Formula: area ~ age + lang * direction + (1 | name) + (1 | story)
   Data: iqr

REML criterion at convergence: 10618.2

Scaled residuals: 
    Min      1Q  Median      3Q     Max 
-1.0106 -0.2805 -0.1782 -0.0233 15.8517 

Random effects:
 Groups   Name        Variance Std.Dev.
 name     (Intercept)  1710669 1307.9  
 story    (Intercept)    31917  178.7  
 Residual             27599545 5253.5  
Number of obs: 534, groups:  name, 35; story, 8

Fixed effects:
                          Estimate Std. Error        df t value Pr(>|t|)  
(Intercept)               2544.897   1172.877    39.578   2.170   0.0361 *
age                         -8.878     16.888    33.501  -0.526   0.6026  
langSE                     175.276    786.530    72.890   0.223   0.8243  
directionreversed          881.472    691.160   362.380   1.275   0.2030  
langSE:directionreversed -1285.287    920.306   402.617  -1.397   0.1633  
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Correlation of Fixed Effects:
            (Intr) age    langSE drctnr
age         -0.860                     
langSE      -0.393  0.012              
dirctnrvrsd -0.295 -0.001  0.442       
lngSE:drctn  0.217  0.007 -0.580 -0.752
#ggcoef(area_lm)

Plotting Viewing Area

medians <- iqr %>%
  group_by(name,lang,direction) %>%
  summarise(xIQR = mean(xIQR,na.rm=TRUE),
                   yIQR = mean(yIQR,na.rm=TRUE),
                   xmed = mean(xmed,na.rm=TRUE),
                   ymed = mean(ymed,na.rm=TRUE)) %>%
  group_by(lang,direction) %>% 
  summarise(xIQR = mean(xIQR,na.rm=TRUE),
                   yIQR = mean(yIQR,na.rm=TRUE),
                   x = mean(xmed,na.rm=TRUE),
                   y = mean(ymed,na.rm=TRUE)) %>%
  mutate(y = y*-1,
         xmin = x-(xIQR/2),
         xmax = x+(xIQR/2),
         ymin = y-(yIQR/2),
         ymax = y+(yIQR/2))
img <- png::readPNG("cindy.png")
g <- grid::rasterGrob(img, interpolate=TRUE, width=unit(1,"npc"), height=unit(1,"npc")) 
ggplot(medians, aes(fill=direction,color=direction)) +
  annotation_custom(g, xmin=-Inf, xmax=Inf, ymin=-Inf, ymax=Inf) +
  geom_rect(aes(xmin=xmin,ymin=ymin,xmax=xmax,ymax=ymax),alpha=.1) + 
  theme_linedraw() +
  scale_x_continuous(limits = c(0,1080), expand = c(0, 0)) +
  scale_y_continuous(limits = c(-720,0), expand = c(0, 0)) +
  facet_wrap("lang")

XY Space Data - Multiple Plots

First let’s prep the data.

multiples <- xydata %>%
  filter(!is.na(x)) %>%
  filter(!is.na(y)) %>%
  group_by(name, age, lang, story, direction, trial) %>%
  summarise(xIQR = IQR(x,na.rm=TRUE),
            yIQR = IQR(y,na.rm=TRUE),
            xmed = median(x, na.rm=TRUE),
            ymed = median(y, na.rm=TRUE),
            area = xIQR*yIQR,
            x_90 = quantile(x, .95, na.rm=TRUE) - quantile(x, .05, na.rm=TRUE),
            y_90 = quantile(y, .95, na.rm=TRUE) - quantile(y, .05, na.rm=TRUE),
            area_90 = (x_90) * (y_90),
            x_mean = mean(x, na.rm = TRUE),
            y_mean = mean(y, na.rm = TRUE),
            x_sd = sd(x, na.rm = TRUE),
            y_sd = sd(y, na.rm = TRUE),
            x_1sd = (x_mean+x_sd) - (x_mean-x_sd),
            y_1sd = (y_mean+y_sd) - (y_mean-y_sd),
            area_1sd = x_1sd * y_1sd,
            x_2sd = (x_mean+(x_sd*2)) - (x_mean-(x_sd*2)),
            y_2sd = (y_mean+(y_sd*2)) - (y_mean-(y_sd*2)),
            area_2sd = x_2sd * y_2sd) %>%
  group_by(name, lang, direction) %>%
  summarise_if(is.double, funs(mean), na.rm = T) %>%
  group_by(lang, direction) %>%
  summarise_if(is.double, funs(mean), na.rm = T)
img <- png::readPNG("cindy.png")
g <- grid::rasterGrob(img, interpolate=TRUE, width=unit(1,"npc"), height=unit(1,"npc")) 

IQR (Middle 50%)

Let’s see.

curr_data <- multiples %>% 
  ungroup() %>%
  select(lang, direction, xmed, ymed, xIQR, yIQR) %>%
  group_by(lang, direction) %>%
  summarise(xmin = xmed-(xIQR/2),
         xmax = xmed+(xIQR/2),
         ymin = -1*(ymed-(yIQR/2)),
         ymax = -1*(ymed+(yIQR/2)))
ggplot(curr_data, aes(fill=direction,color=direction)) +
  annotation_custom(g, xmin=-Inf, xmax=Inf, ymin=-Inf, ymax=Inf) +
  geom_rect(aes(xmin=xmin,ymin=ymin,xmax=xmax,ymax=ymax),alpha=.1) + 
  theme_linedraw() +
  scale_x_continuous(limits = c(0,1080), expand = c(0, 0)) +
  scale_y_continuous(limits = c(-720,0), expand = c(0, 0)) +
  facet_wrap("lang")

Middle 90%

So I calculated the average median across, and the middle 90% of the data.

curr_data <- multiples %>% 
  ungroup() %>%
  select(lang, direction, xmed, ymed, x_90, y_90) %>%
  group_by(lang, direction) %>%
  summarise(xmin = xmed-(x_90/2),
         xmax = xmed+(x_90/2),
         ymin = -1*(ymed-(y_90/2)),
         ymax = -1*(ymed+(y_90/2)))
ggplot(curr_data, aes(fill=direction,color=direction)) +
  annotation_custom(g, xmin=-Inf, xmax=Inf, ymin=-Inf, ymax=Inf) +
  geom_rect(aes(xmin=xmin,ymin=ymin,xmax=xmax,ymax=ymax),alpha=.1) + 
  theme_linedraw() +
  scale_x_continuous(limits = c(0,1080), expand = c(0, 0)) +
  scale_y_continuous(limits = c(-720,0), expand = c(0, 0)) +
  facet_wrap("lang")

# ggplot(filter(curr_data, lang == "NSE"), aes(fill=direction,color=direction)) +
#   annotation_custom(g, xmin=-Inf, xmax=Inf, ymin=-Inf, ymax=Inf) +
#   geom_rect(aes(xmin=xmin,ymin=ymin,xmax=xmax,ymax=ymax),alpha=.2, size = 1) +
#   theme_linedraw() +
#   scale_x_continuous(limits = c(0,1080), expand = c(0, 0)) +
#   scale_y_continuous(limits = c(-720,0), expand = c(0, 0))
# 
# 
# ggplot(filter(curr_data, lang == "SE"), aes(fill=direction,color=direction)) +
#   annotation_custom(g, xmin=-Inf, xmax=Inf, ymin=-Inf, ymax=Inf) +
#   geom_rect(aes(xmin=xmin,ymin=ymin,xmax=xmax,ymax=ymax),alpha=.2, size = 1) +
#   theme_linedraw() +
#   scale_x_continuous(limits = c(0,1080), expand = c(0, 0)) +
#   scale_y_continuous(limits = c(-720,0), expand = c(0, 0))

±1 SD (Middle 68%)

So this is using the mean of the means, plus or minus one SD. This is equivalent to middle 68%.

curr_data <- multiples %>% 
  ungroup() %>%
  select(lang, direction, x_mean, y_mean, x_1sd, y_1sd) %>%
  group_by(lang, direction) %>%
  summarise(xmin = x_mean-(x_1sd/2),
         xmax = x_mean+(x_1sd/2),
         ymin = -1*(y_mean-(y_1sd/2)),
         ymax = -1*(y_mean+(y_1sd/2)))
ggplot(curr_data, aes(fill=direction,color=direction)) +
  annotation_custom(g, xmin=-Inf, xmax=Inf, ymin=-Inf, ymax=Inf) +
  geom_rect(aes(xmin=xmin,ymin=ymin,xmax=xmax,ymax=ymax),alpha=.1) + 
  theme_linedraw() +
  scale_x_continuous(limits = c(0,1080), expand = c(0, 0)) +
  scale_y_continuous(limits = c(-720,0), expand = c(0, 0)) +
  facet_wrap("lang")

±2 SD (Middle 96%)

And this is using the mean of the means, plus or minus two SD. This is equivalent to middle 96%.

curr_data <- multiples %>% 
  ungroup() %>%
  select(lang, direction, x_mean, y_mean, x_2sd, y_2sd) %>%
  group_by(lang, direction) %>%
  summarise(xmin = x_mean-(x_2sd/2),
         xmax = x_mean+(x_2sd/2),
         ymin = -1*(y_mean-(y_2sd/2)),
         ymax = -1*(y_mean+(y_2sd/2)))
ggplot(curr_data, aes(fill=direction,color=direction)) +
  annotation_custom(g, xmin=-Inf, xmax=Inf, ymin=-Inf, ymax=Inf) +
  geom_rect(aes(xmin=xmin,ymin=ymin,xmax=xmax,ymax=ymax),alpha=.1) + 
  theme_linedraw() +
  scale_x_continuous(limits = c(0,1080), expand = c(0, 0)) +
  scale_y_continuous(limits = c(-720,0), expand = c(0, 0)) +
  facet_wrap("lang")

LS0tCnRpdGxlOiAiQ2hpbGRyZW4gLSBTdHVkeSAyIC0gUmVzdWx0cyIKb3V0cHV0OiAKICBodG1sX25vdGVib29rOgogICAgY29kZV9mb2xkaW5nOiBoaWRlCiAgICB0aGVtZTogc3BhY2VsYWIKICAgIGhpZ2hsaWdodDogdGFuZ28KICAgIHRvYzogeWVzCiAgICB0b2NfZGVwdGg6IDIKICAgIHRvY19mbG9hdDogeWVzCiAgICBkZl9wcmludDogcGFnZWQKLS0tCgpUaGlzIGlzIHRoZSByZXN1bHRzIHNlY3Rpb24gZm9yIHRoZSBTdHVkeSAyIE5TRSAmIFNFIENISUxEUkVOIHdhdGNoaW5nIEFTTCBTdG9yaWVzLiBXZSBoYXZlIHR3byBtYWluIGZhY3RvcnM6IAoKMS4gTGFuZ3VhZ2UgKFNpZ24gdi4gRW5nbGlzaCkKMS4gRGlyZWN0aW9uIChGb3J3YXJkIHYuIFJldmVyc2VkKQoKV2UgYXJlIHRha2luZyBvdXQgb25lIG9sZGVyIEtPREEgKEV0aGFuLCAxMC41IHlycykgdG8gYmFsYW5jZSB0aGUgZ3JvdXBzIGJldHRlci4gCgojIERlbW9ncmFwaGljcwpgYGB7ciBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQpsaWJyYXJ5KHRpZHl2ZXJzZSkKbGlicmFyeShqYW5pdG9yKQpsaWJyYXJ5KGxtZTQpCmxpYnJhcnkobG1lclRlc3QpCmxpYnJhcnkoc2NhbGVzKQpsaWJyYXJ5KGZlYXRoZXIpCmxpYnJhcnkoR0dhbGx5KQoKa2lkcyA8LSByZWFkX2ZlYXRoZXIoImNsZWFuZWRjaGlsZGV5ZWRhdGEuZmVhdGhlciIpICU+JQojICBtdXRhdGUoYWdlID0gYWdlKjEyKSAlPiUKICBzZWxlY3QocGFydGljaXBhbnQsIGxhbmd1YWdlLCBhZ2UsIGdlbmRlciwgc3RvcnksIGRpcmVjdGlvbiwgbWFyaywgdHJpYWwsIHJlcGV0aXRpb24sIGFvaSwgc2VjcywgcGVyY2VudCkgJT4lCiAgcmVuYW1lKG5hbWUgPSBwYXJ0aWNpcGFudCkgJT4lCiAgZmlsdGVyKGFnZSA8IDkpICU+JSAjIFRha2Ugb3V0IEV0aGFuCiAgIyBtdXRhdGUoYWdlZ3JvdXAgPSBjYXNlX3doZW4oCiAgIyAgIGFnZSA8PSA4Ljk5IH4gInlvdW5nZXIiLAogICMgICBhZ2UgPj0gOS4wICYgYWdlIDwgMTUgfiAib2xkZXIiCiAgIyApKSAlPiUKICAjIGZpbHRlcighaXMubmEoYWdlZ3JvdXApKSAlPiUKICBtdXRhdGUobGFuZ3VhZ2UgPSBjYXNlX3doZW4oCiAgICBsYW5ndWFnZSA9PSAiZW5nbGlzaCIgfiAiTlNFIiwKICAgIGxhbmd1YWdlID09InNpZ24iIH4gIlNFIgogICkpICU+JQogIHJlbmFtZShsYW5nID0gbGFuZ3VhZ2UpCgpraWRzaW5mbyA8LSBraWRzICU+JQogIHNlbGVjdChuYW1lLCBsYW5nLCBhZ2UsIGdlbmRlcikgJT4lCiAgZGlzdGluY3QoKSAlPiUKICBncm91cF9ieShsYW5nKSAlPiUKICBzdW1tYXJpc2UoTiA9IG4oKSwKICAgICAgICAgICAgYWdlX21lYW4gPSBtZWFuKGFnZSksCiAgICAgICAgICAgIHNkID0gc2QoYWdlKSwKICAgICAgICAgICAgbWluID0gbWluKGFnZSksCiAgICAgICAgICAgIG1heCA9IG1heChhZ2UpKQoKZ2VuZGVycyA8LSBraWRzICU+JQogIHNlbGVjdChuYW1lLCBsYW5nLCBhZ2UsIGdlbmRlcikgJT4lCiAgZGlzdGluY3QoKSAlPiUKICBncm91cF9ieShsYW5nLCBnZW5kZXIpICU+JQogIHN1bW1hcmlzZShOID0gbigpKSAlPiUKICBzcHJlYWQoZ2VuZGVyLCBOKQoKa2lkc2luZm8gPC0gbGVmdF9qb2luKGtpZHNpbmZvLCBnZW5kZXJzKSAlPiUKICBzZWxlY3QobGFuZywgTiwgRmVtYWxlLCBNYWxlLCBhZ2VfbWVhbiwgc2QsIG1pbiwgbWF4KSAlPiUKICBwcmludCgpCgojIGJhYmllcyRhZ2Vncm91cCA8LSBmY3RfcmVsZXZlbChiYWJpZXMkYWdlZ3JvdXAsIGMoInlvdW5nZXIiLCJvbGRlciIpKQoKCiMgSUYgd2UgZG8gYWdlIGdyb3VwcywgdXNlIHRoaXMgY29kZQojIAojIGJhYmllc2luZm8gPC0gYmFiaWVzICU+JQojICAgc2VsZWN0KG5hbWUsIGxhbmcsIGFnZSwgYWdlZ3JvdXAsIGdlbmRlcikgJT4lCiMgICBkaXN0aW5jdCgpICU+JQojICAgZ3JvdXBfYnkobGFuZywgYWdlZ3JvdXApICU+JQojICAgc3VtbWFyaXNlKE4gPSBuKCksCiMgICAgICAgICAgICAgYWdlX21lYW4gPSBtZWFuKGFnZSksCiMgICAgICAgICAgICAgc2QgPSBzZChhZ2UpLAojICAgICAgICAgICAgIG1pbiA9IG1pbihhZ2UpLAojICAgICAgICAgICAgIG1heCA9IG1heChhZ2UpKQojIAojIGdlbmRlcnMgPC0gYmFiaWVzICU+JQojICAgc2VsZWN0KG5hbWUsIGxhbmcsIGFnZSwgYWdlZ3JvdXAsIGdlbmRlcikgJT4lCiMgICBkaXN0aW5jdCgpICU+JQojICAgZ3JvdXBfYnkobGFuZywgYWdlZ3JvdXAsIGdlbmRlcikgJT4lCiMgICBzdW1tYXJpc2UoTiA9IG4oKSkgJT4lCiMgICBzcHJlYWQoZ2VuZGVyLCBOKQojIAojIGJhYmllc2luZm8gPC0gbGVmdF9qb2luKGJhYmllc2luZm8sIGdlbmRlcnMpICU+JQojICAgc2VsZWN0KGxhbmcsIGFnZWdyb3VwLCBOLCBGZW1hbGUsIE1hbGUsIGFnZV9tZWFuLCBzZCwgbWluLCBtYXgpICU+JQojICAgcHJpbnQoKQpgYGAKCkxldCdzIHBsb3QgdGhlIGFnZXMsIGFuZCBjaGVjayBpZiB0aGVyZSBpcyBzaWduaWZpY2FudCBkaWZmZXJlbmNlIGluIGFnZXMgYmV0d2VlbiB0aGUgdHdvIGdyb3Vwcz8KCmBgYHtyfQojIEJveHBsb3QKa2lkcyAlPiUKICBzZWxlY3QobmFtZSwgYWdlLCBsYW5nKSAlPiUKICBkaXN0aW5jdCgpICU+JQogIGdncGxvdChhZXMoeCA9IGxhbmcsIHkgPSBhZ2UsIGZpbGwgPSBsYW5nKSkgKyBnZW9tX2JveHBsb3Qod2lkdGggPSAwLjUpICsgZ3VpZGVzKGZpbGwgPSBGQUxTRSkKCmtpZHMgJT4lCiAgc2VsZWN0KG5hbWUsIGFnZSwgbGFuZykgJT4lCiAgZGlzdGluY3QoKSAlPiUKICBnZ3Bsb3QoYWVzKHggPSBhZ2UsIGZpbGwgPSBsYW5nKSkgKyBnZW9tX2hpc3RvZ3JhbSgpICsgZmFjZXRfZ3JpZChsYW5nIH4gLikKCgojIFQtdGVzdApuc2VfYWdlIDwtIGtpZHMgJT4lIGZpbHRlcihsYW5nID09ICJOU0UiKSAlPiUgc2VsZWN0KG5hbWUsIGFnZSkgJT4lIGRpc3RpbmN0KCkKc2VfYWdlIDwtIGtpZHMgJT4lIGZpbHRlcihsYW5nID09ICJTRSIpICU+JSBzZWxlY3QobmFtZSwgYWdlKSAlPiUgZGlzdGluY3QoKQp0LnRlc3QobnNlX2FnZSRhZ2UsIHNlX2FnZSRhZ2UpCmBgYAoKCiMgR2xvYmFsIExvb2tpbmcKCkZvciBjaGlsZHJlbiwgd2UgY2FsY3VsYXRlZCBwZXJjZW50YWdlcyAqYmFzZWQgb24gb3ZlcmFsbCBjbGlwIGxlbmd0aCogYXMgdGhlIGRlbm9taW5hdG9yLiBJbiB0aGlzIHdheSwgd2UgY2FuIG1lYW5pbmdmdWxseSBjb250cmFzdCBsb29raW5nIHRpbWVzIGF0IHRoZSB2aWRlb3MgKHdoaWNoIGFyZSB2YXJpYWJsZSBsZW5ndGhzKSBiYXNlZCBvbiBkaWZmZXJlbnQgZmFjdG9ycy4gQnV0IHdoZW4gd2UgZ28gdG8gQU9JIGFuYWx5c2lzIHdlIG5lZWQgdG8gcmUtY2FsY3VsYXRlIHRoZSBwZXJjZW50YWdlcyBzbyB0aGUgZGVub21pbmF0b3IgaXMgYmFzZWQgb24gdG90YWwgbG9va2luZyB0aW1lLCBub3Qgb3ZlcmFsbCBjbGlwIGxlbmd0aC4gCgpUaGUgY2hhcnQgYmVsb3cgc2hvd3MgdGhlcmUgc2VlbXMgdG8gYmUgYW4gZWZmZWN0IG9mIGFnZTsgb2xkZXIga2lkcyBsb29rIGxvbmdlciBhdCBpdCB0aGFuIHlvdW5nZXIga2lkcy4gTWF5YmUgbm90IHRvbyBzdXJwcmlzaW5nLiBJdCBtZWFucyB3ZSBuZWVkIHRvIGtlZXAgYWdlIGluIGFueSBtb2RlbHMgd2UgcnVuLiBMZXQncyBhbmFseXplIGEgYml0IG1vcmUgYmVsb3cuCgpgYGB7cn0Ka2lkcyRsYW5nIDwtIGFzLmZhY3RvcihraWRzJGxhbmcpCmtpZHNfb3ZlcmFsbF9sb29raW5nIDwtIGtpZHMgJT4lCiAgZ3JvdXBfYnkobmFtZSwgYWdlLCBsYW5nLCBkaXJlY3Rpb24sIHN0b3J5LCByZXBldGl0aW9uKSAlPiUKICBzdW1tYXJpc2UocGVyY2VudCA9IHN1bShwZXJjZW50KSkgIyBnZXRzIHRvdGFsIGxvb2tpbmcgcGVyY2VudCBmb3IgZWFjaCB0cmlhbCBmb3IgZWFjaCBraWQKCiMgVGFibGUgb2YgbWVhbnMKa2lkc19vdmVyYWxsX2xvb2tpbmcgJT4lIAogIGdyb3VwX2J5KG5hbWUsIGxhbmcsIGRpcmVjdGlvbikgJT4lCiAgc3VtbWFyaXNlKHBlcmNlbnQgPSBtZWFuKHBlcmNlbnQpKSAlPiUgIyBnZXQgYXZlcmFnZSBsb29raW5nIHBlcmNlbnQgZm9yIGVhY2gga2lkCiAgZ3JvdXBfYnkobGFuZywgZGlyZWN0aW9uKSAlPiUKICBzdW1tYXJpc2UobWVhbl9wZXJjZW50ID0gbWVhbihwZXJjZW50KSwKICAgICAgICAgICAgY291bnQgPSBuKCksCiAgICAgICAgICAgIHNkID0gc2QocGVyY2VudCksCiAgICAgICAgICAgIHNlID0gc2Qvc3FydChjb3VudCkpICU+JQogIHNlbGVjdCgtc2QpICU+JQogIHByaW50KCkKCmdncGxvdChraWRzX292ZXJhbGxfbG9va2luZywgYWVzKHggPSBhZ2UsIHkgPSBwZXJjZW50LCBjb2xvciA9IGRpcmVjdGlvbiwgZmlsbCA9IGRpcmVjdGlvbikpICsgCiAgZ2VvbV9qaXR0ZXIoYWxwaGEgPSAwLjUpICsKICBmYWNldF9ncmlkKC4gfiBsYW5nKSArCiAgZ2VvbV9zbW9vdGgobWV0aG9kID0gImxtIiwgc2UgPSBUUlVFKSArCiAgZ2d0aXRsZSgiVmlkZW8gQXR0ZW50aW9uIikgKwogIHhsYWIoImFnZSAobW9udGhzKSIpICsKICB5bGFiKCJwZXJjZW50IGxvb2tpbmciKSArIAogIHRoZW1lX2J3KCkgKyAKICBzY2FsZV95X2NvbnRpbnVvdXMobGltaXRzID0gYygwLDEpLCBsYWJlbHMgPSBwZXJjZW50KSAKCgojIFBsb3QKIyBiYWJpZXNfb3ZlcmFsbF9sb29raW5nICU+JSAKIyAgIGdyb3VwX2J5KGxhbmcsIGRpcmVjdGlvbiwgbmFtZSkgJT4lCiMgICBzdW1tYXJpc2UocGVyY2VudCA9IG1lYW4ocGVyY2VudCkpICU+JSAjIGdldHMgYXZlcmFnZSBsb29raW5nIHBlcmNlbnQgZm9yIGVhY2ggYmFieQojICAgZ3JvdXBfYnkobGFuZywgZGlyZWN0aW9uKSAlPiUKIyAgIHN1bW1hcmlzZShtZWFuX3BlcmNlbnQgPSBtZWFuKHBlcmNlbnQpLCAjIGdldHMgZ3JvdXAgYXZlcmFnZXMKIyAgICAgICAgICAgICBjb3VudCA9IG4oKSwKIyAgICAgICAgICAgICBzZCA9IHNkKHBlcmNlbnQpLAojICAgICAgICAgICAgIHNlID0gc2Qvc3FydChjb3VudCkpICU+JSAKIyAgIGdncGxvdChhZXMoeCA9IGxhbmcsIHkgPSBtZWFuX3BlcmNlbnQsIGZpbGwgPSBkaXJlY3Rpb24pKSArIAojICAgZ2VvbV9jb2wocG9zaXRpb24gPSAiZG9kZ2UiKSArIAojICAgZ2VvbV9lcnJvcmJhcihhZXMoeW1pbiA9IG1lYW5fcGVyY2VudCAtIHNlLCB5bWF4ID0gbWVhbl9wZXJjZW50ICsgc2UpLCAKIyAgICAgICAgICAgICAgICAgcG9zaXRpb24gPSBwb3NpdGlvbl9kb2RnZSh3aWR0aCA9IDAuOSksIHdpZHRoID0gMC4yNSkgKyAKIyAgIHNjYWxlX3lfY29udGludW91cyhsaW1pdHMgPSBjKDAsMSksIGxhYmVscyA9IHBlcmNlbnQpICsKIyAgIHRoZW1lX21pbmltYWwoKSArIAojICAgdGhlbWUocGFuZWwuZ3JpZC5tYWpvci54ID0gZWxlbWVudF9ibGFuaygpKSArCiMgIyAgZmFjZXRfd3JhcCgibGFuZyIpICsKIyAgIGdndGl0bGUoIlZpZGVvIEF0dGVudGlvbiIpICsKIyAgIHhsYWIoIiIpICsKIyAgIHlsYWIoInBlcmNlbnQgbG9va2luZyIpCgojIGJhYmllc19vdmVyYWxsX2xvb2tpbmcgJT4lCiMgICBnZ3Bsb3QoYWVzKHggPSBsYW5nLCB5ID0gcGVyY2VudCwgZmlsbCA9IGRpcmVjdGlvbikpICsKIyAgIGZhY2V0X3dyYXAoImFnZWdyb3VwIikgKyAKIyAgIGdlb21fdmlvbGluKCkKYGBgCgpBIGxpbmVhciBtb2RlbCBzaG93cyBhIHNpZ25pZmljYW50IGVmZmVjdCBvZiBhZ2UuIE92ZXJhbGwsIEFnZSBzZWVtcyB0byBpbmNyZWFzZSBvdmVyYWxsIGxvb2tpbmcgYnkgYWJvdXQgMyUgZXZlcnkgeWVhci4gSG93ZXZlciwgdGhlcmUgYXJlIG5vIGRpZmZlcmVuY2VzIGJldHdlZW4gTlNFIHYuIFNFLCBvciByZXZlcnNhbCwgb24gaG93IGxvbmcgdGhleSBsb29rZWQsIHNvIHRoYXQncyBnb29kLiAKCmBgYHtyfQpnbG9iYWxfbG0gPC0gbG1lcihwZXJjZW50IH4gYWdlICsgbGFuZyAqIGRpcmVjdGlvbiArICgxfG5hbWUpICsgKDF8c3RvcnkpLCBkYXRhID0ga2lkc19vdmVyYWxsX2xvb2tpbmcpCnN1bW1hcnkoZ2xvYmFsX2xtKQojZ2djb2VmKGdsb2JhbF9sbSkKYGBgCgojIEFPSSBMb29raW5nCk5vdyB3ZSdsbCByZS1jYWxjdWxhdGUgdGhlIHBlcmNlbnRhZ2VzIHNvIHRoZSBkZW5vbWluYXRvciBpcyBiYXNlZCBvbiB0b3RhbCBsb29raW5nIHRpbWUuIEFsbCBBT0lzIHNob3VsZCBzdW0gdXAgdG8gMTAwJSBmb3IgZWFjaCB0cmlhbCBhbmQgZWFjaCBiYWJ5LiBOZXh0IGxldCdzIG1ha2UgYSBib3hwbG90IG9mIGFsbCBBT0lzLiBJbnRlcmVzdGluZywgZGVmaW5pdGVseSBtb3JlIE1pZEZhY2VCb3R0b20gZm9jdXMgaGVyZSB0aGFuIHdlIGhhZCB3aXRoIGJhYmllcywgYnV0IGFsc28gbW9yZSBkaXN0cmlidXRpb24gdG9vLgoKYGBge3J9CiMgUmVjYWxjdWxhdGUgcGVyY2VudApraWRzIDwtIGtpZHMgJT4lIAogIHNlbGVjdCgtcGVyY2VudCkgJT4lCiAgZ3JvdXBfYnkobmFtZSwgbGFuZywgYWdlLCBkaXJlY3Rpb24sIHN0b3J5LCBtYXJrLCB0cmlhbCwgcmVwZXRpdGlvbikgJT4lCiAgbXV0YXRlKHRvdGFsc2VjID0gc3VtKHNlY3MpKSAlPiUKICBncm91cF9ieShuYW1lLCBsYW5nLCBhZ2UsIGRpcmVjdGlvbiwgc3RvcnksIG1hcmssIHRyaWFsLCByZXBldGl0aW9uLCBhb2kpICU+JQogIHN1bW1hcmlzZShwZXJjZW50ID0gc2Vjcy90b3RhbHNlYykKCiMgQm94cGxvdApraWRzICU+JQogIGdncGxvdChhZXMoeCA9IGFvaSwgeSA9IHBlcmNlbnQsIGZpbGwgPSBkaXJlY3Rpb24pKSArIAogIGdlb21fYm94cGxvdCgpICsKICBnZ3RpdGxlKCJBT0kgQXR0ZW50aW9uIikgKwogIHRoZW1lX2J3KCkgKyAKICB4bGFiKCIiKSArCiAgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGU9NDUsIGhqdXN0ID0gMSksCiAgICAgICAgcGFuZWwuZ3JpZC5tYWpvci54ID0gZWxlbWVudF9ibGFuaygpKSArCiAgc2NhbGVfeV9jb250aW51b3VzKGxhYmVscyA9IHNjYWxlczo6cGVyY2VudCwgbGltaXRzID0gYygwLDEpKQpgYGAKSXQgYXBwZWFycyB0d28gaW1wb3J0YW50IEFPSXMgYXJlIE1pZENoZXN0VG9wIGFuZCBNaWRGYWNlQm90dG9tLiBMZXQncyBsb29rIGFnYWluIG9ubHkgYXQgbWlkbGluZSBBT0lzOgoKYGBge3J9Cm1pZGxpbmUgPSBjKCJCZWxseSIsIkJlbG93Q2hlc3QiLCJNaWRDaGVzdEJvdHRvbSIsIk1pZENoZXN0Q2VudGVyIiwiTWlkQ2hlc3RUb3AiLAogICAgICAgICAgICAiTWlkRmFjZUJvdHRvbSIsIk1pZEZhY2VDZW50ZXIiLCJNaWRGYWNlVG9wIikKa2lkcyAlPiUKICBmaWx0ZXIoYW9pICVpbiUgbWlkbGluZSkgJT4lCiAgZ2dwbG90KGFlcyh4ID0gYW9pLCB5ID0gcGVyY2VudCwgZmlsbCA9IGRpcmVjdGlvbikpICsgCiAgZ2VvbV9ib3hwbG90KCkgKwogIGdndGl0bGUoIk1pZGxpbmUgQU9JIEF0dGVudGlvbiIpICsKICB0aGVtZV9idygpICsgCiAgeGxhYigiIikgKwogIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlPTQ1LCBoanVzdCA9IDEpLAogICAgICAgIHBhbmVsLmdyaWQubWFqb3IueCA9IGVsZW1lbnRfYmxhbmsoKSkgKwogIHNjYWxlX3lfY29udGludW91cyhsYWJlbHMgPSBzY2FsZXM6OnBlcmNlbnQsIGxpbWl0cyA9IGMoMCwxKSkKYGBgCgpJJ20gZ29pbmcgdG8gcnVuIGxpbmVhciBtb2RlbHMgd2l0aCBvbmx5IE1pZENoZXN0VG9wIG9yIE1pZEZhY2VCb3R0b20sIGFuZCBzZWUgd2hhdCBoYXBwZW5zLiBObyBhZ2UgaW50ZXJhY3Rpb25zLgoKKipNaWRDaGVzdFRvcDoqKgoKKiBObyBlZmZlY3Qgb2YgYWdlLgoqIE5vIGVmZmVjdCBvZiBsYW5ndWFnZS4KKiAqV2VhayogZWZmZWN0IG9mIGRpcmVjdGlvbiAocCA9IDAuMDg0KSAtIHJldmVyc2VkIG1lYW5zIHRoZXkgbG9vayB+IDQuNyUgbGVzcyBhdCBtaWRjaGVzdHRvcC4KKiBObyBsYW5ndWFnZSBYIGRpcmVjdGlvbiBpbnRlcmFjdGlvbi4gCgoKKipNaWRGYWNlQm90dG9tOioqIAoKKiBObyBlZmZlY3Qgb2YgYWdlLgoqIFNpZ25pZmljYW50IGVmZmVjdCBvZiBsYW5ndWFnZSAocCA9IDAuMDA0KSAtIFNFIGxvb2sgYXQgTWlkRmFjZUJvdHRvbSArMTklIG1vcmUgdGhhbiBOU0UgY2hpbGRyZW4KKiBObyBlZmZlY3Qgb2YgZGlyZWN0aW9uLgoqIE5vIGxhbmd1YWdlIFggZGlyZWN0aW9uIGludGVyYWN0aW9uLgoKCmBgYHtyfQpraWRzICU+JQogIGZpbHRlcihhb2kgJWluJSBjKCJNaWRGYWNlQm90dG9tIiwiTWlkQ2hlc3RUb3AiKSkgJT4lCiAgZ2dwbG90KGFlcyh4ID0gYWdlLCB5ID0gcGVyY2VudCwgY29sb3IgPSBkaXJlY3Rpb24sIGZpbGwgPSBkaXJlY3Rpb24pKSArIAogIGdlb21faml0dGVyKGFscGhhID0gMC41KSArIAogIGdlb21fc21vb3RoKG1ldGhvZCA9ICJsbSIsIHNlID0gRkFMU0UpICsKICBzY2FsZV95X2NvbnRpbnVvdXMobGltaXRzID0gYygwLDEpLCBsYWJlbHMgPSBwZXJjZW50KSArCiAgdGhlbWVfYncoKSArIAojICB0aGVtZShwYW5lbC5ncmlkLm1ham9yLnggPSBlbGVtZW50X2JsYW5rKCkpICsKICBmYWNldF9ncmlkKGFvaSB+IGxhbmcpICsKICBnZ3RpdGxlKCJBT0kgQXR0ZW50aW9uIikgKwogIHhsYWIoIiIpICsKICB5bGFiKCJwZXJjZW50IGxvb2tpbmciKQoKbWlkY2hlc3R0b3BfbG0gPC0gbG1lcihwZXJjZW50IH4gYWdlICsgbGFuZyAqIGRpcmVjdGlvbiArICgxfG5hbWUpICsgKDF8c3RvcnkpLCBkYXRhID0gZmlsdGVyKGtpZHMsIGFvaSA9PSAiTWlkQ2hlc3RUb3AiKSkKc3VtbWFyeShtaWRjaGVzdHRvcF9sbSkKI2dnY29lZihtaWRjaGVzdHRvcF9sbSkKCm1pZGZhY2Vib3R0b21fbG0gPC0gbG1lcihwZXJjZW50IH4gYWdlICsgbGFuZyAqIGRpcmVjdGlvbiArICgxfG5hbWUpICsgKDF8c3RvcnkpLCBkYXRhID0gZmlsdGVyKGtpZHMsIGFvaSA9PSAiTWlkRmFjZUJvdHRvbSIpKQpzdW1tYXJ5KG1pZGZhY2Vib3R0b21fbG0pCiNnZ2NvZWYobWlkZmFjZWJvdHRvbV9sbSkKCiMgQmFyIGNoYXJ0CiMgYmFiaWVzICU+JQojICAgZmlsdGVyKGFvaSAlaW4lIGMoIk1pZEZhY2VCb3R0b20iLCJNaWRDaGVzdFRvcCIpKSAlPiUKIyAgIGdyb3VwX2J5KGFnZWdyb3VwLCBsYW5nLCBkaXJlY3Rpb24sIG5hbWUsIGFvaSkgJT4lCiMgICBzdW1tYXJpc2UocGVyY2VudCA9IG1lYW4ocGVyY2VudCkpICU+JSAjIGdldHMgYXZlcmFnZSBsb29raW5nIHBlcmNlbnQgZm9yIGVhY2ggYmFieQojICAgZ3JvdXBfYnkoYWdlZ3JvdXAsIGxhbmcsIGRpcmVjdGlvbiwgYW9pKSAlPiUKIyAgIHN1bW1hcmlzZShtZWFuX3BlcmNlbnQgPSBtZWFuKHBlcmNlbnQpLCAjIGdldHMgZ3JvdXAgYXZlcmFnZXMKIyAgICAgICAgICAgICBjb3VudCA9IG4oKSwKIyAgICAgICAgICAgICBzZCA9IHNkKHBlcmNlbnQpLAojICAgICAgICAgICAgIHNlID0gc2Qvc3FydChjb3VudCkpICU+JSAKIyAgIGdncGxvdChhZXMoeCA9IGxhbmcsIHkgPSBtZWFuX3BlcmNlbnQsIGZpbGwgPSBkaXJlY3Rpb24pKSArIAojICAgZ2VvbV9jb2wocG9zaXRpb24gPSAiZG9kZ2UiKSArIAojICAgZ2VvbV9lcnJvcmJhcihhZXMoeW1pbiA9IG1lYW5fcGVyY2VudCAtIHNlLCB5bWF4ID0gbWVhbl9wZXJjZW50ICsgc2UpLCAKIyAgICAgICAgICAgICAgICAgcG9zaXRpb24gPSBwb3NpdGlvbl9kb2RnZSh3aWR0aCA9IDAuOSksIHdpZHRoID0gMC4yNSkgKyAKIyAgIHNjYWxlX3lfY29udGludW91cyhsaW1pdHMgPSBjKDAsMSksIGxhYmVscyA9IHBlcmNlbnQpICsKIyAgIHRoZW1lX21pbmltYWwoKSArIAojICAgdGhlbWUocGFuZWwuZ3JpZC5tYWpvci54ID0gZWxlbWVudF9ibGFuaygpKSArCiMgICBmYWNldF9ncmlkKGFvaSB+IGFnZWdyb3VwKSArCiMgICBnZ3RpdGxlKCJWaWRlbyBBdHRlbnRpb24iKSArCiMgICB4bGFiKCIiKSArCiMgICB5bGFiKCJwZXJjZW50IGxvb2tpbmciKQpgYGAKCgojIEZhY2UtQ2hlc3QgUmF0aW8KTmV4dCwgd2UnbGwgZGVmaW5lIGEgRmFjZS1DaGVzdCBSYXRpbyAoRkNSKSBzdWNoIHRoYXQ6CgoxLiBNaWRGYWNlQ2VudGVyLCBNaWRGYWNlQm90dG9tID0gRmFjZQoxLiBNaWRDaGVzdFRvcCwgTWlkQ2hlc3RDZW50ZXIsIE1pZENoZXN0Qm90dG9tLCBCZWxvd0NoZXN0ID0gQ2hlc3QKMS4gRkNSID0gZmFjZSAtIGNoZXN0IC8gZmFjZSArIGNoZXN0CgpXZSBkaWQgbm90IGluY2x1ZGUgQmVsbHkgb3IgTWlkRmFjZVRvcCBiZWNhdXNlIG9mIHZlcnkgbG93IGxvb2tpbmcgcmF0ZXMgYWNjb3JkaW5nIHRvIHRoZSBib3hwbG90cyBhYm92ZS4KCmBgYHtyfQpraWRzX2ZjciA8LSBraWRzICU+JQogIHNwcmVhZChhb2kscGVyY2VudCkgJT4lCiAgZ3JvdXBfYnkobmFtZSwgYWdlLCBsYW5nLCBkaXJlY3Rpb24sIHN0b3J5LCByZXBldGl0aW9uKSAlPiUKICBzdW1tYXJpc2UoZmFjZSA9IHN1bShNaWRGYWNlQ2VudGVyLCBNaWRGYWNlQm90dG9tLCBuYS5ybSA9IFRSVUUpLAogICAgICAgICBjaGVzdCA9IHN1bShNaWRDaGVzdFRvcCwgTWlkQ2hlc3RDZW50ZXIsIE1pZENoZXN0Qm90dG9tLCBCZWxvd0NoZXN0LCBuYS5ybSA9IFRSVUUpLAogICAgICAgICBmY3IgPSAoZmFjZSAtIGNoZXN0KSAvIChmYWNlICsgY2hlc3QpKQoKIyBUYWJsZSBvZiBtZWFucwpraWRzX2ZjciAlPiUgCiAgZ3JvdXBfYnkobGFuZywgZGlyZWN0aW9uLCBuYW1lKSAlPiUKICBzdW1tYXJpc2UoZmNyID0gbWVhbihmY3IpKSAlPiUgIyBnZXRzIGF2ZXJhZ2UgbG9va2luZyBwZXJjZW50IGZvciBlYWNoIGJhYnkKICBncm91cF9ieShsYW5nLCBkaXJlY3Rpb24pICU+JQogIHN1bW1hcmlzZShtZWFuX2ZjciA9IG1lYW4oZmNyKSwgIyBnZXRzIGdyb3VwIGF2ZXJhZ2VzCiAgICAgICAgICAgIGNvdW50ID0gbigpLAogICAgICAgICAgICBzZCA9IHNkKGZjciksCiAgICAgICAgICAgIHNlID0gc2Qvc3FydChjb3VudCkpICU+JQogIHNlbGVjdCgtc2QpICU+JQogIHByaW50KCkKCiMgUGxvdApnZ3Bsb3Qoa2lkc19mY3IsIGFlcyh4ID0gYWdlLCB5ID0gZmNyLCBjb2xvciA9IGRpcmVjdGlvbiwgZmlsbCA9IGRpcmVjdGlvbikpICsgCiAgZ2VvbV9obGluZSh5aW50ZXJjZXB0ID0gMCwgbGluZXR5cGUgPSAiZGFzaGVkIikgKwogIGdlb21faml0dGVyKGFscGhhID0gMC41KSArIAogIGdlb21fc21vb3RoKG1ldGhvZCA9ICJsbSIsIHNlID0gRkFMU0UpICsKICBzY2FsZV95X2NvbnRpbnVvdXMobGltaXRzID0gYygtMSwxKSkgKwogIHRoZW1lX2J3KCkgKyAKICB0aGVtZShwYW5lbC5ncmlkLm1ham9yLnggPSBlbGVtZW50X2JsYW5rKCkpICsKICBmYWNldF9ncmlkKC4gfiBsYW5nKSArCiAgZ2d0aXRsZSgiRmFjZS1DaGVzdCBSYXRpb3MiKSArCiAgeGxhYigiIikgKwogIHlsYWIoIkZDUiIpCgojIEJhciBjaGFydAojIGJhYmllc19mY3IgJT4lIAojICAgZ3JvdXBfYnkoYWdlZ3JvdXAsIGxhbmcsIGRpcmVjdGlvbiwgbmFtZSkgJT4lCiMgICBzdW1tYXJpc2UoZmNyID0gbWVhbihmY3IpKSAlPiUgIyBnZXRzIGF2ZXJhZ2UgbG9va2luZyBwZXJjZW50IGZvciBlYWNoIGJhYnkKIyAgIGdyb3VwX2J5KGFnZWdyb3VwLCBsYW5nLCBkaXJlY3Rpb24pICU+JQojICAgc3VtbWFyaXNlKG1lYW5fZmNyID0gbWVhbihmY3IpLCAjIGdldHMgZ3JvdXAgYXZlcmFnZXMKIyAgICAgICAgICAgICBjb3VudCA9IG4oKSwKIyAgICAgICAgICAgICBzZCA9IHNkKGZjciksCiMgICAgICAgICAgICAgc2UgPSBzZC9zcXJ0KGNvdW50KSkgJT4lIAojICAgZ2dwbG90KGFlcyh4ID0gbGFuZywgeSA9IG1lYW5fZmNyLCBmaWxsID0gZGlyZWN0aW9uKSkgKyAKIyAgIGdlb21fY29sKHBvc2l0aW9uID0gImRvZGdlIikgKyAKIyAgIGdlb21fZXJyb3JiYXIoYWVzKHltaW4gPSBtZWFuX2ZjciAtIHNlLCB5bWF4ID0gbWVhbl9mY3IgKyBzZSksIAojICAgICAgICAgICAgICAgICBwb3NpdGlvbiA9IHBvc2l0aW9uX2RvZGdlKHdpZHRoID0gMC45KSwgd2lkdGggPSAwLjI1KSArIAojICAgc2NhbGVfeV9jb250aW51b3VzKGxpbWl0cyA9IGMoLTEsMSkpICsKIyAgIHRoZW1lX21pbmltYWwoKSArIAojICAgdGhlbWUocGFuZWwuZ3JpZC5tYWpvci54ID0gZWxlbWVudF9ibGFuaygpKSArCiMgICBmYWNldF93cmFwKCJhZ2Vncm91cCIpICsKIyAgIGdndGl0bGUoIkZhY2UtQ2hlc3QgUmF0aW9zIikgKwojICAgeGxhYigiIikgKwojICAgeWxhYigiRkNSIikKYGBgCgpXaGF0IHdpbGwgYSBsaW5lYXIgbWl4ZWQgbW9kZWwgdGVsbCB1cz8gKHdpdGggbm8gYWdlIGludGVyYWN0aW9ucykKCiogTm8gZWZmZWN0IG9mIGFnZS4gSW50ZXJlc3RpbmcuIE1heWJlIGp1c3QgYmVjdWFzZSB3ZSBkb24ndCBoYXZlIHRoYXQgbWFueSBiYWJpZXMuIAoqIEVmZmVjdCBvZiBsYW5ndWFnZTogU0UgYmFiaWVzIGhhdmUgb3ZlcmFsbCArMC4zNiBGQ1IgdGhhbiBOU0UgYmFiaWVzIChwID0gMC4wMykuIFNFIGxvb2tzIGF0IHRoZSBmYWNlIG1vcmUgdGhhbiB0aGUgY2hlc3QuIAoqIE5vIGVmZmVjdCBvZiBkaXJlY3Rpb24uIEludGVyZXN0aW5nLiAKKiBObyBpbnRlcmFjdGlvbi4gSW50ZXJlc3RpbmcuIAoKYGBge3J9CmZjcl9sbSA8LSBsbWVyKGZjciB+IGFnZSArIGxhbmcgKiBkaXJlY3Rpb24gKyAoMXxuYW1lKSArICgxfHN0b3J5KSwgZGF0YSA9IGtpZHNfZmNyKQpzdW1tYXJ5KGZjcl9sbSkKI2dnY29lZihmY3JfbG0pCmBgYAoKIyBWaXN1YWxpemluZyBSZXZlcnNhbCBFZmZlY3QKSSB3YW50IHRvIHRyeSB0byB2aXN1YWxpemUgcmV2ZXJzYWwgZWZmZWN0cyBhIGRpZmZlcmVudCB3YXkuIE1heWJlIHRoaXMuIAoKYGBge3J9CiMgR2V0IHBhcnRpY2lwYW50LWxldmVsIGRhdGEKa2lkc19mY3IyIDwtIGtpZHNfZmNyICU+JQogIGdyb3VwX2J5KG5hbWUsIGFnZSwgbGFuZywgZGlyZWN0aW9uKSAlPiUKICBzdW1tYXJpc2UoZmNyID0gbWVhbihmY3IpKQoKIyByZXZlcnNhbF9lZmZlY3RfbG0gPC0gbG1lcihmY3IgfiBhZ2UgKyBsYW5nICogZGlyZWN0aW9uICsgKDF8bmFtZSksIGRhdGEgPSBraWRzX2ZjcjIpCiMgc3VtbWFyeShyZXZlcnNhbF9lZmZlY3RfbG0pCgpnZ3Bsb3Qoa2lkc19mY3IyLCBhZXMoeCA9IGRpcmVjdGlvbiwgeSA9IGZjciwgY29sb3IgPSBsYW5nLCBmaWxsID0gbGFuZykpICsKICBnZW9tX3BvaW50KCkgKwogIGdlb21fbGluZShhZXMoZ3JvdXAgPSBuYW1lKSkgKwogIGZhY2V0X2dyaWQoLiB+IGxhbmcpICsgCiAgc2NhbGVfeV9jb250aW51b3VzKGxpbWl0cyA9IGMoLTEsMSkpICsKICB0aGVtZV9idygpCgpgYGAKCk9yIGEgcmV2ZXJzYWwgZWZmZWN0IGNoYXJ0PyBPa2F5LCBzbyB0aGlzIGNoYXJ0IHRlbGxzIHVzIG92ZXJhbGwgdGhlcmUgcmVhbGx5IHdhc24ndCBtdWNoIG9mIGEgcmV2ZXJzYWwgZWZmZWN0IGZvciBTRSBiYWJpZXMsIHRoZXkncmUgYWxsIGhvdmVyaW5nIGFyb3VuZCAwLiBJbnRlcmVzdGluZy4gV2hpbGUgdGhlcmUgc2VlbXMgdG8gYmUgYSByZXZlcnNhbCBlZmZlY3QgZm9yIE5TRSBiYWJpZXMgd2hlcmUgdGhleSBsb29rIGF0IHRoZSBmYWNlIG1vcmUgZHVyaW5nIHJldmVyc2VkIHN0b3JpZXMhIAoKYGBge3J9CiMgR2V0IHBhcnRpY2lwYW50LWxldmVsIGRhdGEKa2lkc19mY3IzIDwtIGtpZHNfZmNyMiAlPiUKICBzcHJlYWQoZGlyZWN0aW9uLCBmY3IpICU+JQogIGdyb3VwX2J5KG5hbWUsIGFnZSwgbGFuZykgJT4lCiAgc3VtbWFyaXNlKGRpZmYgPSBmb3J3YXJkIC0gcmV2ZXJzZWQpCgpnZ3Bsb3Qoa2lkc19mY3IzLCBhZXMoeCA9IGFnZSwgeSA9IGRpZmYsIGNvbG9yID0gbGFuZykpICsKICBnZW9tX3BvaW50KCkgKwogIGdlb21fc21vb3RoKG1ldGhvZCA9ICJsbSIsIHNlID0gRkFMU0UpICsKICBzY2FsZV95X2NvbnRpbnVvdXMobGltaXRzID0gYygtMSwxKSkgKwogIHRoZW1lX2J3KCkgKwogIGdndGl0bGUoIlJldmVyc2FsIEVmZmVjdCIpICsKICB5bGFiKCJGb3J3YXJkIEZDUiAtIFJldmVyc2VkIEZDUiIpCmBgYAoKQW5kIHdpdGhpbi1zdWJqZWN0cyB2YXJpYXRpb24gaGVyZTogCgpgYGB7cn0KIyBGaXJzdCBnZXQgdGhlIG1lYW4gb2YgZWFjaCB0cmlhbCwgVEhFTiB0aGUgcGFydGljaXBhbnQtbGV2ZWwgbWVhbnMKd2l0aGluX3N1YmplY3RzIDwtIGtpZHNfZmNyICU+JQogIGdyb3VwX2J5KG5hbWUsIGxhbmcsIGRpcmVjdGlvbiwgc3RvcnksIHJlcGV0aXRpb24pICU+JQogIHN1bW1hcmlzZShmY3IgPSBtZWFuKGZjciwgbmEucm0gPSBUUlVFKSwKICAgICAgICAgICAgY291bnQgPSBuKCkpICU+JQogIGdyb3VwX2J5KG5hbWUsIGxhbmcsIGRpcmVjdGlvbikgJT4lCiAgc3VtbWFyaXNlKG1lYW4gPSBtZWFuKGZjciwgbmEucm0gPSBUUlVFKSwKICAgICAgICAgICAgc2UgPSBzZChmY3IsIG5hLnJtID0gVFJVRSkvc3FydChuKCkpLAogICAgICAgICAgICBjb3VudCA9IG4oKSkKIyBUaGVuIHNwcmVhZCBvdXQgbWVhbiBhbmQgU0UgY29sdW1ucyBieSBkaXJlY3Rpb24Kd2l0aGluX3N1YmplY3RzX21lYW5zIDwtIHdpdGhpbl9zdWJqZWN0cyAlPiUKICBzZWxlY3QoLXNlLCAtY291bnQpICU+JQogIHNwcmVhZChkaXJlY3Rpb24sIG1lYW4sIHNlcCA9ICJfIikKd2l0aGluX3N1YmplY3RzX3NlIDwtIHdpdGhpbl9zdWJqZWN0cyAlPiUKICBzZWxlY3QoLW1lYW4sIC1jb3VudCkgJT4lCiAgc3ByZWFkKGRpcmVjdGlvbiwgc2UsIHNlcCA9ICJTRSIpCndpdGhpbl9zdWJqZWN0cyA8LSBsZWZ0X2pvaW4od2l0aGluX3N1YmplY3RzX21lYW5zLCB3aXRoaW5fc3ViamVjdHNfc2UsIGJ5ID0gYygibmFtZSIsImxhbmciKSkKCiMgTm93IGxldCdzIHBsb3QKbGltcyA8LSBjKC0xLDEpCndpdGhpbl9zdWJqZWN0cyAlPiUKICBnZ3Bsb3QoYWVzKHggPSBkaXJlY3Rpb25fZm9yd2FyZCwgeSA9IGRpcmVjdGlvbl9yZXZlcnNlZCwgY29sb3IgPSBsYW5nKSkgKwogICAgZ2VvbV9hYmxpbmUoKSArCiAgZ2VvbV9wb2ludChzaXplID0gMikgKyAKICBnZW9tX2Vycm9yYmFyKGFlcyh5bWluPWRpcmVjdGlvbl9yZXZlcnNlZC1kaXJlY3Rpb25TRXJldmVyc2VkLCB5bWF4PWRpcmVjdGlvbl9yZXZlcnNlZCtkaXJlY3Rpb25TRXJldmVyc2VkKSkgKwogIGdlb21fZXJyb3JiYXJoKGFlcyh4bWluPWRpcmVjdGlvbl9mb3J3YXJkLWRpcmVjdGlvblNFZm9yd2FyZCwgeG1heD1kaXJlY3Rpb25fZm9yd2FyZCtkaXJlY3Rpb25TRWZvcndhcmQpKSArCiAgdGhlbWVfYncoKSArCiAgdGhlbWUoYXNwZWN0LnJhdGlvID0gMSkgKwogIHNjYWxlX3hfY29udGludW91cygiZm9yd2FyZCIsIGxpbWl0cyA9IGMoLTEsMSkpICsKICBzY2FsZV95X2NvbnRpbnVvdXMoInJldmVyc2VkIiwgbGltaXRzID0gYygtMSwxKSkgKwogIGdndGl0bGUoIkZDUiBNZWFucyIpICsKICBmYWNldF93cmFwKCJsYW5nIikKYGBgCgpBbmQgYSBjbGFzc2ljIGJveC9lcnJvciBwbG90IHdpdGggYWdlIGNvbGxhcHNlZC4gCgpgYGB7cn0Ka2lkc19mY3IyICU+JQogIGdyb3VwX2J5KGxhbmcsIGRpcmVjdGlvbikgJT4lCiAgc3VtbWFyaXNlKGZjcl9tZWFuID0gbWVhbihmY3IpLAogICAgICAgICAgICBzZCA9IHNkKGZjciksCiAgICAgICAgICAgIG4gPSBuKCksCiAgICAgICAgICAgIHNlID0gc2Qvc3FydChuKSkgJT4lCiAgZ2dwbG90KGFlcyh4ID0gbGFuZywgeSA9IGZjcl9tZWFuLCBmaWxsID0gZGlyZWN0aW9uKSkgKwogIGdlb21fYmFyKHN0YXQgPSAiaWRlbnRpdHkiLCBwb3NpdGlvbiA9IHBvc2l0aW9uX2RvZGdlKCkpICsgCiAgZ2VvbV9lcnJvcmJhcihhZXMoeW1pbiA9IGZjcl9tZWFuLXNlLCB5bWF4ID0gZmNyX21lYW4rc2UpLCBwb3NpdGlvbiA9IHBvc2l0aW9uX2RvZGdlKDAuOSksIHdpZHRoID0gMC4yKSArCiAgc2NhbGVfeV9jb250aW51b3VzKGxpbWl0cyA9IGMoLTAuNSwgMC41KSkgKwogIHRoZW1lX2xpbmVkcmF3KCkKCmBgYAoKYGBge3IgZmlnLndpZHRoPTYuNSwgZmlnLmhlaWdodD02fQoKbGlicmFyeShleHRyYWZvbnQpCgpraWRzX2ZjcjIgJT4lCiAgZ3JvdXBfYnkobGFuZywgZGlyZWN0aW9uKSAlPiUKICBzdW1tYXJpc2UoZmNyX21lYW4gPSBtZWFuKGZjciksCiAgICAgICAgICAgIHNkID0gc2QoZmNyKSwKICAgICAgICAgICAgbiA9IG4oKSwKICAgICAgICAgICAgc2UgPSBzZC9zcXJ0KG4pKSAlPiUKICBnZ3Bsb3QoYWVzKHggPSBsYW5nLCB5ID0gZmNyX21lYW4sIGNvbG9yID0gZGlyZWN0aW9uLCBmaWxsID0gZGlyZWN0aW9uLCBncm91cCA9IGRpcmVjdGlvbikpICsKICBnZW9tX2hsaW5lKHlpbnRlcmNlcHQgPSAwLCBzaXplID0gMC41KSArCiAgZ2VvbV9wb2ludChzaXplID0gNiwgcG9zaXRpb24gPSBwb3NpdGlvbl9kb2RnZSh3aWR0aCA9IDAuNCkpICsKICBnZW9tX2Vycm9yYmFyKGFlcyh5bWluID0gZmNyX21lYW4tc2UsIHltYXggPSBmY3JfbWVhbitzZSksIAogICAgICAgICAgICAgICAgc2l6ZSA9IDIsIAogICAgICAgICAgICAgICAgcG9zaXRpb24gPSBwb3NpdGlvbl9kb2RnZSgwLjQpLCAKICAgICAgICAgICAgICAgIHdpZHRoID0gMC4zKSArCiAgc2NhbGVfeV9jb250aW51b3VzKGxpbWl0cyA9IGMoLTAuNSwgMC41KSkgKwogIHRoZW1lX2xpbmVkcmF3KCkgKwogIHRoZW1lKHRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDMwLCBmYW1pbHkgPSAieGtjZCIpLAogICAgICAgIHBhbmVsLmdyaWQubWlub3IueSA9IGVsZW1lbnRfYmxhbmsoKSwKICAgICAgICBwYW5lbC5ncmlkLm1ham9yLnggPSBlbGVtZW50X2JsYW5rKCksCiAgICAgICAgYXhpcy50aXRsZS55ID0gZWxlbWVudF9ibGFuaygpLAogICAgICAgIGF4aXMudGl0bGUueCA9IGVsZW1lbnRfYmxhbmsoKSwKICAgICAgICBheGlzLnRleHQueCA9IGVsZW1lbnRfYmxhbmsoKSwKICAgICAgICBheGlzLnRpY2tzLnggPSBlbGVtZW50X2JsYW5rKCksCiAgICAgICAgcGFuZWwuYm9yZGVyID0gZWxlbWVudF9yZWN0KHNpemUgPSAyKSwKICAgICAgICBheGlzLnRpY2tzLnkgPSBlbGVtZW50X2xpbmUoc2l6ZSA9IDAuNSksCiAgICAgICAgcGFuZWwuZ3JpZC5tYWpvci55ID0gZWxlbWVudF9saW5lKHNpemUgPSAwLjUsIGNvbG9yID0gImxpZ2h0IGdyYXkiLCBsaW5ldHlwZSA9ICJkYXNoZWQiKSkgKwogIGd1aWRlcyhjb2xvciA9IEZBTFNFLCBmaWxsID0gRkFMU0UpCgpgYGAKCiMgSGVhdCBNYXBzCkFuZCBub3cgaGVhdCBtYXBzIQoKYGBge3J9CmhlYXRtYXBfa2lkcyA8LSBraWRzICU+JQogIGZpbHRlcihhb2kgJWluJSBtaWRsaW5lKSAlPiUKICB1bmdyb3VwKCkgJT4lCiAgZ3JvdXBfYnkobGFuZywgbmFtZSwgZGlyZWN0aW9uLCBhb2kpICU+JQogIHN1bW1hcmlzZShwZXJjZW50ID0gbWVhbihwZXJjZW50LCBuYS5ybT1UUlVFKSkgJT4lCiAgZ3JvdXBfYnkobGFuZywgZGlyZWN0aW9uLCBhb2kpICU+JQogIHN1bW1hcmlzZShwZXJjZW50ID0gbWVhbihwZXJjZW50LCBuYS5ybT1UUlVFKSkgJT4lCiAgdW5ncm91cCgpICU+JQogIG11dGF0ZShhb2kgPSBmYWN0b3IoYW9pLCBsZXZlbHMgPSBjKCJCZWxseSIsIkJlbG93Q2hlc3QiLCJNaWRDaGVzdEJvdHRvbSIsIk1pZENoZXN0Q2VudGVyIiwiTWlkQ2hlc3RUb3AiLAogICAgICAgICAgICAiTWlkRmFjZUJvdHRvbSIsIk1pZEZhY2VDZW50ZXIiLCJNaWRGYWNlVG9wIikpKQoKZ2dwbG90KGhlYXRtYXBfa2lkcywgYWVzKHggPSBsYW5nLCB5ID0gYW9pKSkgKwogIGdlb21fdGlsZShhZXMoZmlsbD1wZXJjZW50KSxjb2xvcj0ibGlnaHRncmF5IixuYS5ybT1UUlVFKSArIAojICBzY2FsZV9maWxsX3ZpcmlkaXMob3B0aW9uID0gInZpcmlkaXMiLCBkaXJlY3Rpb249LTEsIGxpbWl0cyA9IGMoMCwuNyksIGxhYmVscyA9IHBlcmNlbnQsIG5hbWUgPSAibG9va2luZyB0aW1lIikgKwogICAgc2NhbGVfZmlsbF9ncmFkaWVudChsb3cgPSAiI2ZmZmZmZiIsIGhpZ2ggPSAiIzA4NTE5YyIsIHNwYWNlID0gIkxhYiIsIGxpbWl0cyA9IGMoMCwuNTIpLCBsYWJlbHMgPSBwZXJjZW50LCBuYW1lID0gImxvb2tpbmcgdGltZSIsIG5hLnZhbHVlID0gImdyZXk1MCIpICsKICB0aGVtZV9idygpICsKICB0aGVtZShzdHJpcC50ZXh0LnggPSBlbGVtZW50X3RleHQoc2l6ZSA9IDExLCBjb2xvciA9ICJibGFjayIsIGZhY2UgPSAiaXRhbGljIiksIAogICAgICAgIHN0cmlwLmJhY2tncm91bmQgPSBlbGVtZW50X3JlY3QoY29sb3VyID0gIndoaXRlIiwgZmlsbCA9ICJ3aGl0ZSIpLAogICAgICAgIHBhbmVsLmdyaWQubWFqb3IgPSBlbGVtZW50X2xpbmUoY29sb3IgPSAid2hpdGUiKSkgKwogIGZhY2V0X2dyaWQoLiB+IGRpcmVjdGlvbikgKwogIHlsYWIoIiIpICsgeGxhYigiIikgKyBnZ3RpdGxlKCJFeWUgR2F6ZSBIZWF0IE1hcCwgYnkgRGlyZWN0aW9uIikgKyAKICBzY2FsZV95X2Rpc2NyZXRlKGV4cGFuZD1jKDAsMCkpICsKICBzY2FsZV94X2Rpc2NyZXRlKGV4cGFuZCA9IGMoMCwwKSkKCmdncGxvdChoZWF0bWFwX2tpZHMsIGFlcyh4ID0gZGlyZWN0aW9uLCB5ID0gYW9pKSkgKwogIGdlb21fdGlsZShhZXMoZmlsbD1wZXJjZW50KSxjb2xvcj0ibGlnaHRncmF5IixuYS5ybT1UUlVFKSArIAojICBzY2FsZV9maWxsX3ZpcmlkaXMob3B0aW9uID0gInZpcmlkaXMiLCBkaXJlY3Rpb249LTEsIGxpbWl0cyA9IGMoMCwuNyksIGxhYmVscyA9IHBlcmNlbnQsIG5hbWUgPSAibG9va2luZyB0aW1lIikgKwogICAgc2NhbGVfZmlsbF9ncmFkaWVudChsb3cgPSAiI2ZmZmZmZiIsIGhpZ2ggPSAiIzA4NTE5YyIsIHNwYWNlID0gIkxhYiIsIGxpbWl0cyA9IGMoMCwuNTIpLCBsYWJlbHMgPSBwZXJjZW50LCBuYW1lID0gImxvb2tpbmcgdGltZSIsIG5hLnZhbHVlID0gImdyZXk1MCIpICsKICB0aGVtZV9idygpICsKICB0aGVtZShzdHJpcC50ZXh0LnggPSBlbGVtZW50X3RleHQoc2l6ZSA9IDExLCBjb2xvciA9ICJibGFjayIsIGZhY2UgPSAiaXRhbGljIiksIAogICAgICAgIHN0cmlwLmJhY2tncm91bmQgPSBlbGVtZW50X3JlY3QoY29sb3VyID0gIndoaXRlIiwgZmlsbCA9ICJ3aGl0ZSIpLAogICAgICAgIHBhbmVsLmdyaWQubWFqb3IgPSBlbGVtZW50X2xpbmUoY29sb3IgPSAid2hpdGUiKSkgKwogIGZhY2V0X2dyaWQoLiB+IGxhbmcpICsKICB5bGFiKCIiKSArIHhsYWIoIiIpICsgZ2d0aXRsZSgiRXllIEdhemUgSGVhdCBNYXAsIGJ5IExhbmd1YWdlIikgKyAKICBzY2FsZV95X2Rpc2NyZXRlKGV4cGFuZD1jKDAsMCkpICsKICBzY2FsZV94X2Rpc2NyZXRlKGV4cGFuZCA9IGMoMCwwKSkKYGBgCgoKCmBgYHtyfQojIEFsbCBEYXRhCiNIZXJlJ3MgYWxsIEFPSSBkYXRhLiAKCmtpZHMgJT4lCiAgdW5ncm91cCgpICU+JQogIGdyb3VwX2J5KGxhbmcsIG5hbWUsIGRpcmVjdGlvbiwgYW9pKSAlPiUKICBzdW1tYXJpc2UocGVyY2VudCA9IG1lYW4ocGVyY2VudCwgbmEucm09VFJVRSkpICU+JQogIGdyb3VwX2J5KGxhbmcsIGRpcmVjdGlvbiwgYW9pKSAlPiUKICBzdW1tYXJpc2UocGVyY2VudCA9IG1lYW4ocGVyY2VudCwgbmEucm09VFJVRSkpICU+JQogIG9wZW54bHN4Ojp3cml0ZS54bHN4KCJ+L0Rlc2t0b3Ava2lkc19ieV9kaXJlY3Rpb24ueGxzeCIpCgpraWRzICU+JQogIHVuZ3JvdXAoKSAlPiUKICBncm91cF9ieShsYW5nLCBuYW1lLCBkaXJlY3Rpb24sIGFvaSkgJT4lCiAgc3VtbWFyaXNlKHBlcmNlbnQgPSBtZWFuKHBlcmNlbnQsIG5hLnJtPVRSVUUpKSAlPiUKICBncm91cF9ieShsYW5nLCBkaXJlY3Rpb24sIGFvaSkgJT4lCiAgc3VtbWFyaXNlKHBlcmNlbnQgPSBtZWFuKHBlcmNlbnQsIG5hLnJtPVRSVUUpKSAlPiUKICBncm91cF9ieShsYW5nLCBhb2kpICU+JQogIHN1bW1hcmlzZShwZXJjZW50ID0gbWVhbihwZXJjZW50LCBuYS5ybT1UUlVFKSkgJT4lCiAgb3Blbnhsc3g6OndyaXRlLnhsc3goIn4vRGVza3RvcC9raWRzX2NvbGxhcHNlZC54bHN4IikKYGBgCgojIERpc2N1c3Npb24KTm8gYmlnIGNoYW5nZXMgZnJvbSB0aGUgSUNTTEEgYWJzdHJhY3QuIEdvb2QhIAoKVGhlIGludGVycHJldGF0aW9uIGhlcmUgaXMgdGhhdDoKCiogQWxsIGtpZHMgbG9va2VkIGVxdWFsbHkgYXQgYWxsIHZpZGVvcyByZWdhcmRsZXNzIG9mIGxhbmd1YWdlIG9yIGRpcmVjdGlvbi4gQWdlIGRpZCBoYXZlIGFuIGVmZmVjdCBzbyB3ZSB1c2VkIGFnZSBpbiBvdXIgbW9kZWxzLiBHb29kIQoqIFNFIGtpZHMgY29udGludWUgdG8gYmUgc3Ryb25nIGZhY2UtbG9va2VycyBjb21wYXJlZCB0byBOU0Uga2lkcy4gIChTYW1lIGFzIElDU0xBKQoqIFRoZXJlIGlzIG5vIHJldmVyc2FsIGVmZmVjdC4gKFNhbWUgYXMgSUNTTEEpCgpUaGF0IGRvZXNuJ3QgbWVhbiBib3RoIGdyb3VwcyBvZiBjaGlsZHJlbiBkb24ndCBjYXJlIGFib3V0IHJldmVyc2FsLiBPbiB0aGUgY29udHJhcnkuIFdlIGNhbiBoeXBvdGhlc2l6ZSB0aGF0IFNFIGtpZHMgaGF2ZSBlZmZpY2llbnQgZ2F6ZSBiZWhhdmlvciBhbmQgYXJlIHJlc2lsaWVudCB0byByZXZlcnNhbDsgd2hpbGUgTlNFIGtpZHMgYWxyZWFkeSBhcmUgImluZWZmaWNpZW50IiBhbmQgY2hhbmdpbmcgdGhlIHZpZGVvIHN0aW11bHVzIGlzbid0IGdvaW5nIHRvIGhlbHAuIEJ1dCBob3cgZG8gd2UgdGVzdCB0aGF0PyBNYXliZSBsZXQncyBsb29rIGF0IHdpdGhpbi1zdWJqZWN0IHZhcmlhdGlvbi4KCiMgQ29ycmVsYXRpb25zCkxldCdzIHRyeSBjb3JyZWxhdGlvbnMuCmBgYHtyIGZpZy5oZWlnaHQ9MTIsIGZpZy53aWR0aD0xMn0KIyBMZXQncyB0cnkgY29ycmVsYXRpb25zCmtpZHNfbnNlIDwtIGtpZHMgJT4lIAogIGZpbHRlcihhb2kgJWluJSBtaWRsaW5lKSAlPiUKICBmaWx0ZXIobGFuZyA9PSAiTlNFIikgJT4lCiAgZ3JvdXBfYnkobmFtZSwgZGlyZWN0aW9uLCBhb2kpICU+JSAKICBzdW1tYXJpc2UocGVyY2VudCA9IG1lYW4ocGVyY2VudCkpICU+JQogIHVuZ3JvdXAoKSAlPiUKICBtdXRhdGUoZGlyZWN0aW9uID0gY2FzZV93aGVuKAogICAgZGlyZWN0aW9uID09ICJmb3J3YXJkIiB+ICJmdyIsCiAgICBkaXJlY3Rpb24gPT0gInJldmVyc2VkIiB+ICJydiIKICApKSAlPiUgCiAgdW5pdGUoYW9pMiwgZGlyZWN0aW9uLCBhb2ksIHNlcCA9ICJfIikgJT4lCiAgc3ByZWFkKGFvaTIsIHBlcmNlbnQpICU+JQogIHNlbGVjdCgtbmFtZSkKCmtpZHNfc2UgPC0ga2lkcyAlPiUgCiAgZmlsdGVyKGFvaSAlaW4lIG1pZGxpbmUpICU+JQogIGZpbHRlcihsYW5nID09ICJTRSIpICU+JQogIGdyb3VwX2J5KG5hbWUsIGRpcmVjdGlvbiwgYW9pKSAlPiUgCiAgc3VtbWFyaXNlKHBlcmNlbnQgPSBtZWFuKHBlcmNlbnQpKSAlPiUKICB1bmdyb3VwKCkgJT4lCiAgbXV0YXRlKGRpcmVjdGlvbiA9IGNhc2Vfd2hlbigKICAgIGRpcmVjdGlvbiA9PSAiZm9yd2FyZCIgfiAiZnciLAogICAgZGlyZWN0aW9uID09ICJyZXZlcnNlZCIgfiAicnYiCiAgKSkgJT4lIAogIHVuaXRlKGFvaTIsIGRpcmVjdGlvbiwgYW9pLCBzZXAgPSAiXyIpICU+JQogIHNwcmVhZChhb2kyLCBwZXJjZW50KSAlPiUKICBzZWxlY3QoLW5hbWUpCgpnZ2NvcnIoa2lkc19uc2UsIGxhYmVsID0gVFJVRSwgbGFiZWxfc2l6ZSA9IDUsIGxhYmVsX3JvdW5kID0gMiwgbGFiZWxfYWxwaGEgPSBUUlVFLCBoanVzdCA9IDAuOSwgc2l6ZSA9IDUsIGNvbG9yID0gImdyZXk1MCIsIGxheW91dC5leHAgPSAxKSArIGdndGl0bGUoIk5TRSIpCgpnZ2NvcnIoa2lkc19zZSwgbGFiZWwgPSBUUlVFLCBsYWJlbF9zaXplID0gNSwgbGFiZWxfcm91bmQgPSAyLCBsYWJlbF9hbHBoYSA9IFRSVUUsIGhqdXN0ID0gMC45LCBzaXplID0gNSwgY29sb3IgPSAiZ3JleTUwIiwgbGF5b3V0LmV4cCA9IDEpICsgZ2d0aXRsZSgiU0UiKQoKbGlicmFyeShjb3JycikKa2lkc19uc2UgJT4lIGNvcnJlbGF0ZSgpICU+JSBuZXR3b3JrX3Bsb3QobWluX2Nvcj0wLjYpICsgZ2d0aXRsZSgiTlNFIENoaWxkcmVuIikKa2lkc19zZSAlPiUgY29ycmVsYXRlKCkgJT4lIG5ldHdvcmtfcGxvdChtaW5fY29yPTAuNikgKyBnZ3RpdGxlKCJTRSBDaGlsZHJlbiIpCgpgYGAKCiMgWFkgU3BhY2UgRGF0YQpXZSdsbCBsb2FkIHRoZSBkYXRhIGZyb20gdGhlIGBjaGlsZHh5ZGF0YS5mZWF0aGVyYCBmaWxlIG1hZGUgaW4gMDZyYXd4eWRhdGEuUm1kLiBTbyBhbnkgbmV3IGtpZHMsIHBsZWFzZSBydW4gdGhlIGZpcnN0IGNvZGUgYmxvY2sgaW4gMDYgdG8gaW5jbHVkZSBpdC4gVGhlbiB3ZSdsbCBrZWVwIGFsbCB0aGUga2lkcyB3ZSBhbHNvIGhhdmUgaW4gdGhlIEFPSSBkYXRhIGdyb3VwLiAKCmBgYHtyIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9CmluY2x1ZGVkIDwtIGtpZHMgJT4lCiAgdW5ncm91cCgpICU+JQogIHNlbGVjdChuYW1lKSAlPiUgCiAgZGlzdGluY3QoKSAlPiUKICB1bmxpc3QoKQoKeHlkYXRhIDwtIHJlYWRfZmVhdGhlcigiLi4vQ2hpbGQgRGF0YS9jaGlsZHh5ZGF0YS5mZWF0aGVyIikgJT4lCiAgcmVuYW1lKG5hbWUgPSBwYXJ0aWNpcGFudCkgJT4lCiAgZmlsdGVyKG5hbWUgJWluJSBpbmNsdWRlZCkKCiMgR2V0IGFnZXMKYWdlcyA8LSByZWFkX2NzdigiY2hpbGRyZW5hZ2VzLmNzdiIpICU+JQogIHJlbmFtZShuYW1lID0gcGFydGljaXBhbnQpCnh5ZGF0YSA8LSB4eWRhdGEgJT4lIGxlZnRfam9pbihhZ2VzLCBieSA9ICJuYW1lIikgJT4lCiAgbXV0YXRlKGFnZSA9IGFnZSoxMikgJT4lCiAgbXV0YXRlKGFnZWdyb3VwID0gY2FzZV93aGVuKAogICAgYWdlIDw9IDguOTkgfiAieW91bmdlciIsCiAgICBhZ2UgPj0gOS4wICYgYWdlIDwgMTUgfiAib2xkZXIiCiAgKSkgJT4lCiAgbXV0YXRlKGxhbmd1YWdlID0gY2FzZV93aGVuKAogICAgbGFuZ3VhZ2UgPT0gIkVuZ2xpc2hFeHBvc2VkIiB+ICJOU0UiLAogICAgbGFuZ3VhZ2UgPT0gIlNpZ25MYW5ndWFnZUV4cG9zZWQiIH4gIlNFIgogICkpICU+JQogIHJlbmFtZShsYW5nID0gbGFuZ3VhZ2UpICU+JQogIHNlbGVjdChuYW1lLCBncm91cCwgZ2VuZGVyLCBsYW5nLCBjb25kaXRpb24sIG1hcmssIHRyaWFsLCByZXBldGl0aW9uLCB4LCB5LCBhZ2UsIGFnZWdyb3VwKSAlPiUKICBzZXBhcmF0ZShjb25kaXRpb24sIGludG8gPSBjKCJzdG9yeSIsICJjbGlwIiwgImRpcmVjdGlvbiIpKSAlPiUKICB1bml0ZSgic3RvcnkiLCBjKCJzdG9yeSIsICJjbGlwIikpICU+JQogIG11dGF0ZShkaXJlY3Rpb24gPSBjYXNlX3doZW4oCiAgICBkaXJlY3Rpb24gPT0gIkVSIiB+ICJyZXZlcnNlZCIsCiAgICBkaXJlY3Rpb24gPT0gIkZXIiB+ICJmb3J3YXJkIgogICkpICU+JQogIG11dGF0ZShuYW1lID0gZmFjdG9yKG5hbWUpLAogICAgICAgICBncm91cCA9IGZhY3Rvcihncm91cCksCiAgICAgICAgIGdlbmRlciA9IGZhY3RvcihnZW5kZXIpLAogICAgICAgICBsYW5nID0gZmFjdG9yKGxhbmcpLAogICAgICAgICBzdG9yeSA9IGZhY3RvcihzdG9yeSksCiAgICAgICAgIGRpcmVjdGlvbiA9IGZhY3RvcihkaXJlY3Rpb24pLAogICAgICAgICBtYXJrID0gZmFjdG9yKG1hcmspLAogICAgICAgICB0cmlhbCA9IGZhY3Rvcih0cmlhbCksCiAgICAgICAgIHJlcGV0aXRpb24gPSBmYWN0b3IocmVwZXRpdGlvbiksCiAgICAgICAgIGFnZWdyb3VwID0gZmFjdG9yKGFnZWdyb3VwKSkKYGBgCgojIyBPdmVyYWxsIExvb2tpbmcKTGV0J3MgY2hlY2sgdGhhdCB3ZSBoYXZlIG5vIHNpZ25pZmljYW50IGdyb3VwIG9yIGNvbmRpdGlvbiBkaWZmZXJlbmNlcyBpbiB0ZXJtcyBvZiB2YWxpZCAobm90IGVtcHR5KSBkYXRhIHBvaW50cyBjb2xsZWN0ZWQuIFRoaXMgaXMgc2FtZSBhcyAiR2xvYmFsIExvb2tpbmciIHdlIGhhdmUgYWJvdmUsIHJlYWxseSwgYnV0IHcgcmF3IHh5IGRhdGEuIAoKYGBge3J9Cnh5X292ZXJhbGwgPC0geHlkYXRhICU+JQogIGZpbHRlcighaXMubmEoeCkpICU+JQogIGdyb3VwX2J5KG5hbWUsIGFnZSwgbGFuZywgZGlyZWN0aW9uLCBzdG9yeSwgcmVwZXRpdGlvbikgJT4lCiAgc3VtbWFyaXNlKGRhdGFfcG9pbnRzID0gbigpKSAjIGdldHMgdG90YWwgbG9va2luZyBwZXJjZW50IGZvciBlYWNoIHRyaWFsIGZvciBlYWNoIGJhYnkKCiMgVGFibGUgb2YgbWVhbnMKeHlfb3ZlcmFsbCAlPiUgCiAgZ3JvdXBfYnkobmFtZSwgbGFuZywgZGlyZWN0aW9uKSAlPiUKICBzdW1tYXJpc2UoZGF0YV9wb2ludHMgPSBtZWFuKGRhdGFfcG9pbnRzKSkgJT4lICMgZ2V0IGF2ZXJhZ2UgbG9va2luZyBwZXJjZW50IGZvciBlYWNoIGJhYnkKICBncm91cF9ieShsYW5nLCBkaXJlY3Rpb24pICU+JQogIHN1bW1hcmlzZShtZWFuX2RhdGFfcG9pbnRzID0gbWVhbihkYXRhX3BvaW50cyksCiAgICAgICAgICAgIGNvdW50ID0gbigpLAogICAgICAgICAgICBzZCA9IHNkKGRhdGFfcG9pbnRzKSwKICAgICAgICAgICAgc2UgPSBzZC9zcXJ0KGNvdW50KSkgJT4lCiAgc2VsZWN0KC1zZCkgJT4lCiAgcHJpbnQoKQoKZ2dwbG90KHh5X292ZXJhbGwsIGFlcyh4ID0gYWdlLCB5ID0gZGF0YV9wb2ludHMsIGNvbG9yID0gZGlyZWN0aW9uLCBmaWxsID0gZGlyZWN0aW9uKSkgKyAKICBnZW9tX2ppdHRlcihhbHBoYSA9IDAuNSkgKwogIGZhY2V0X2dyaWQoLiB+IGxhbmcpICsKICBnZW9tX3Ntb290aChtZXRob2QgPSAibG0iLCBzZSA9IEZBTFNFKSArCiAgZ2d0aXRsZSgiRGF0YSBQb2ludHMiKSArCiAgeGxhYigiYWdlIChtb250aHMpIikgKwogIHlsYWIoImRhdGEgcG9pbnRzIHJlY29yZGVkIikgKyAKICB0aGVtZV9idygpIApgYGAKCgpEZXNjcmlwdGlvbi4KCmBgYHtyfQpvdmVyYWxsX3h5X2xtIDwtIGxtZXIoZGF0YV9wb2ludHMgfiBhZ2UgKyBsYW5nICogZGlyZWN0aW9uICsgKGRpcmVjdGlvbnxuYW1lKSArIChkaXJlY3Rpb258c3RvcnkpLCBkYXRhID0geHlfb3ZlcmFsbCkKc3VtbWFyeShvdmVyYWxsX3h5X2xtKSAKI2dnY29lZihvdmVyYWxsX3h5X2xtKQpgYGAKCiMjIFhZIERhdGEgTE1NcwpOb3cgd2UncmUgZ29pbmcgdG8gcnVuIExNTXMgb24gYmFiaWVzJyByYXc6IAoKKiBob3Jpem9udGFsIHNwcmVhZCAobWlkZGxlIDUwJSBvZiB4IGRhdGE7IHhJUVIpCiogdmVydGljYWwgc3ByZWFkIChtaWRkbGUgNTAlIG9mIHkgZGF0YTsgeUlRUikKKiB2aWV3aW5nIGFyZWEgKEEgPSBtaWRkbGUteCAqIG1pZGRsZS15OyBhcmVhKQoKQnV0IHRvIGRvIHRoaXMgd2UgZmlyc3QgdHJpbSBlYWNoIGtpZCdzIGRhdGEsIGdldHRpbmcgcmlkIG9mIHRoZSBmaXJzdCA2MCBzYW1wbGVzICgwLjUwIHNlY3MpIG9mIGVhY2ggdHJpYWwuIAoKYGBge3J9Cnh5ZGF0YSA8LSB4eWRhdGEgJT4lCiAgZ3JvdXBfYnkobmFtZSx0cmlhbCkgJT4lCiAgc2xpY2UoMzA6bigpKQoKaXFyIDwtIHh5ZGF0YSAlPiUKICBncm91cF9ieShuYW1lLCBhZ2UsIGxhbmcsIHN0b3J5LCBkaXJlY3Rpb24sIHRyaWFsKSAlPiUKICBzdW1tYXJpc2UoeElRUiA9IElRUih4LG5hLnJtPVRSVUUpLAogICAgICAgICAgICAgICAgICAgeUlRUiA9IElRUih5LG5hLnJtPVRSVUUpLAogICAgICAgICAgICAgICAgICAgeG1lZCA9IG1lZGlhbih4LCBuYS5ybT1UUlVFKSwKICAgICAgICAgICAgICAgICAgIHltZWQgPSBtZWRpYW4oeSwgbmEucm09VFJVRSksCiAgICAgICAgICAgICAgICAgICBhcmVhID0geElRUip5SVFSKQpoZWFkKGlxciwyMCkKCmBgYAoKCiMjIyBNaWRkbGUgWApEZXNjcmlwdGlvbi4KCmBgYHtyfQp4aXFyX21lYW4gPC0gaXFyICU+JSAKICBncm91cF9ieShsYW5nLCBkaXJlY3Rpb24sIG5hbWUpICU+JQogIHN1bW1hcmlzZSh4SVFSID0gbWVhbih4SVFSLCBuYS5ybSA9IFQpKSAlPiUgIyBnZXRzIGF2ZXJhZ2UgbG9va2luZyBwZXJjZW50IGZvciBlYWNoIGJhYnkKICBncm91cF9ieShsYW5nLCBkaXJlY3Rpb24pICU+JQogIHN1bW1hcmlzZShtZWFuX3hJUVIgPSBtZWFuKHhJUVIpLCAjIGdldHMgZ3JvdXAgYXZlcmFnZXMKICAgICAgICAgICAgY291bnQgPSBuKCksCiAgICAgICAgICAgIHNkID0gc2QoeElRUiksCiAgICAgICAgICAgIHNlID0gc2Qvc3FydChjb3VudCkpICU+JQogIHNlbGVjdCgtc2QpICU+JQogIHByaW50KCkKCiMgUGxvdApnZ3Bsb3QoaXFyLCBhZXMoeCA9IGFnZSwgeSA9IHhJUVIsIGNvbG9yID0gZGlyZWN0aW9uLCBmaWxsID0gZGlyZWN0aW9uKSkgKyAKICBnZW9tX2ppdHRlcihhbHBoYSA9IDAuNSkgKyAKICBnZW9tX3Ntb290aChtZXRob2QgPSAibG0iLCBzZSA9IEZBTFNFKSArCiAgdGhlbWVfYncoKSArIAogIHRoZW1lKHBhbmVsLmdyaWQubWFqb3IueCA9IGVsZW1lbnRfYmxhbmsoKSkgKwogIGZhY2V0X2dyaWQoLiB+IGxhbmcpICsKICBnZ3RpdGxlKCJIb3Jpem9udGFsIFNwcmVhZCIpICsKICB4bGFiKCIiKSArCiAgeWxhYigieElRUiIpCgpnZ3Bsb3QoeGlxcl9tZWFuLCBhZXMoeCA9IGxhbmcsIHkgPSBtZWFuX3hJUVIsIGZpbGwgPSBkaXJlY3Rpb24pKSArCiAgZ2VvbV9iYXIoc3RhdCA9ICJpZGVudGl0eSIsIHBvc2l0aW9uID0gcG9zaXRpb25fZG9kZ2UoKSkgKyAKICBnZW9tX2Vycm9yYmFyKGFlcyh5bWluID0gbWVhbl94SVFSLXNlLCB5bWF4ID0gbWVhbl94SVFSK3NlKSwgcG9zaXRpb24gPSBwb3NpdGlvbl9kb2RnZSgwLjkpLCB3aWR0aCA9IDAuMikgKwogIHRoZW1lX2xpbmVkcmF3KCkKCnhpcXJfbG0gPC0gbG1lcih4SVFSIH4gYWdlICsgbGFuZyAqIGRpcmVjdGlvbiArICgxfG5hbWUpICsgKDF8c3RvcnkpLCBkYXRhID0gaXFyKQpzdW1tYXJ5KHhpcXJfbG0pCiNnZ2NvZWYoeGlxcl9sbSkKYGBgCgoKIyMjIE1pZGRsZSBZCkRlc2NyaXB0aW9uLgoKYGBge3J9CnlpcXJfbWVhbiA8LSBpcXIgJT4lIAogIGdyb3VwX2J5KGxhbmcsIGRpcmVjdGlvbiwgbmFtZSkgJT4lCiAgc3VtbWFyaXNlKHlJUVIgPSBtZWFuKHlJUVIsIG5hLnJtID0gVCkpICU+JSAjIGdldHMgYXZlcmFnZSBsb29raW5nIHBlcmNlbnQgZm9yIGVhY2ggYmFieQogIGdyb3VwX2J5KGxhbmcsIGRpcmVjdGlvbikgJT4lCiAgc3VtbWFyaXNlKG1lYW5feUlRUiA9IG1lYW4oeUlRUiksICMgZ2V0cyBncm91cCBhdmVyYWdlcwogICAgICAgICAgICBjb3VudCA9IG4oKSwKICAgICAgICAgICAgc2QgPSBzZCh5SVFSKSwKICAgICAgICAgICAgc2UgPSBzZC9zcXJ0KGNvdW50KSkgJT4lCiAgc2VsZWN0KC1zZCkgJT4lCiAgcHJpbnQoKQoKIyBQbG90CmdncGxvdChpcXIsIGFlcyh4ID0gYWdlLCB5ID0geUlRUiwgY29sb3IgPSBkaXJlY3Rpb24sIGZpbGwgPSBkaXJlY3Rpb24pKSArIAogIGdlb21faml0dGVyKGFscGhhID0gMC41KSArIAogIGdlb21fc21vb3RoKG1ldGhvZCA9ICJsbSIsIHNlID0gRkFMU0UpICsKICB0aGVtZV9idygpICsgCiAgdGhlbWUocGFuZWwuZ3JpZC5tYWpvci54ID0gZWxlbWVudF9ibGFuaygpKSArCiAgZmFjZXRfZ3JpZCguIH4gbGFuZykgKwogIGdndGl0bGUoIlZlcnRpY2FsIFNwcmVhZCIpICsKICB4bGFiKCIiKSArCiAgeWxhYigieUlRUiIpCgpnZ3Bsb3QoeWlxcl9tZWFuLCBhZXMoeCA9IGxhbmcsIHkgPSBtZWFuX3lJUVIsIGZpbGwgPSBkaXJlY3Rpb24pKSArCiAgZ2VvbV9iYXIoc3RhdCA9ICJpZGVudGl0eSIsIHBvc2l0aW9uID0gcG9zaXRpb25fZG9kZ2UoKSkgKyAKICBnZW9tX2Vycm9yYmFyKGFlcyh5bWluID0gbWVhbl95SVFSLXNlLCB5bWF4ID0gbWVhbl95SVFSK3NlKSwgcG9zaXRpb24gPSBwb3NpdGlvbl9kb2RnZSgwLjkpLCB3aWR0aCA9IDAuMikgKwogIHRoZW1lX2xpbmVkcmF3KCkKCnlpcXJfbG0gPC0gbG1lcih5SVFSIH4gYWdlICsgbGFuZyAqIGRpcmVjdGlvbiArICgxfG5hbWUpICsgKDF8c3RvcnkpLCBkYXRhID0gaXFyKQpzdW1tYXJ5KHlpcXJfbG0pCiNnZ2NvZWYoeWlxcl9sbSkKYGBgCgojIyMgVmlld2luZyBBcmVhCkRlc2NyaXB0aW9uLgoKYGBge3J9CmFyZWFfbWVhbiA8LSBpcXIgJT4lIAogIGdyb3VwX2J5KGxhbmcsIGRpcmVjdGlvbiwgbmFtZSkgJT4lCiAgc3VtbWFyaXNlKGFyZWEgPSBtZWFuKGFyZWEsIG5hLnJtID0gVCkpICU+JSAjIGdldHMgYXZlcmFnZSBsb29raW5nIHBlcmNlbnQgZm9yIGVhY2ggYmFieQogIGdyb3VwX2J5KGxhbmcsIGRpcmVjdGlvbikgJT4lCiAgc3VtbWFyaXNlKGFyZWFfbWVhbiA9IG1lYW4oYXJlYSksICMgZ2V0cyBncm91cCBhdmVyYWdlcwogICAgICAgICAgICBjb3VudCA9IG4oKSwKICAgICAgICAgICAgc2QgPSBzZChhcmVhKSwKICAgICAgICAgICAgc2UgPSBzZC9zcXJ0KGNvdW50KSkgJT4lCiAgc2VsZWN0KC1zZCkgJT4lCiAgcHJpbnQoKQoKIyBQbG90CmdncGxvdChpcXIsIGFlcyh4ID0gYWdlLCB5ID0gYXJlYSwgY29sb3IgPSBkaXJlY3Rpb24sIGZpbGwgPSBkaXJlY3Rpb24pKSArIAogIGdlb21faml0dGVyKGFscGhhID0gMC41KSArIAogIGdlb21fc21vb3RoKG1ldGhvZCA9ICJsbSIsIHNlID0gRkFMU0UpICsKICB0aGVtZV9idygpICsgCiAgdGhlbWUocGFuZWwuZ3JpZC5tYWpvci54ID0gZWxlbWVudF9ibGFuaygpKSArCiAgZmFjZXRfZ3JpZCguIH4gbGFuZykgKwogIGdndGl0bGUoIlZpZXdpbmcgQXJlYSIpICsKICB4bGFiKCIiKSArCiAgeWxhYigiQXJlYSAocHheMikiKQoKZ2dwbG90KGFyZWFfbWVhbiwgYWVzKHggPSBsYW5nLCB5ID0gYXJlYV9tZWFuLCBmaWxsID0gZGlyZWN0aW9uKSkgKwogIGdlb21fYmFyKHN0YXQgPSAiaWRlbnRpdHkiLCBwb3NpdGlvbiA9IHBvc2l0aW9uX2RvZGdlKCkpICsgCiAgZ2VvbV9lcnJvcmJhcihhZXMoeW1pbiA9IGFyZWFfbWVhbi1zZSwgeW1heCA9IGFyZWFfbWVhbitzZSksIHBvc2l0aW9uID0gcG9zaXRpb25fZG9kZ2UoMC45KSwgd2lkdGggPSAwLjIpICsKICB0aGVtZV9saW5lZHJhdygpCgphcmVhX2xtIDwtIGxtZXIoYXJlYSB+IGFnZSArIGxhbmcgKiBkaXJlY3Rpb24gKyAoMXxuYW1lKSArICgxfHN0b3J5KSwgZGF0YSA9IGlxcikKc3VtbWFyeShhcmVhX2xtKQojZ2djb2VmKGFyZWFfbG0pCmBgYAoKIyMgUGxvdHRpbmcgVmlld2luZyBBcmVhIAoKYGBge3J9Cm1lZGlhbnMgPC0gaXFyICU+JQogIGdyb3VwX2J5KG5hbWUsbGFuZyxkaXJlY3Rpb24pICU+JQogIHN1bW1hcmlzZSh4SVFSID0gbWVhbih4SVFSLG5hLnJtPVRSVUUpLAogICAgICAgICAgICAgICAgICAgeUlRUiA9IG1lYW4oeUlRUixuYS5ybT1UUlVFKSwKICAgICAgICAgICAgICAgICAgIHhtZWQgPSBtZWFuKHhtZWQsbmEucm09VFJVRSksCiAgICAgICAgICAgICAgICAgICB5bWVkID0gbWVhbih5bWVkLG5hLnJtPVRSVUUpKSAlPiUKICBncm91cF9ieShsYW5nLGRpcmVjdGlvbikgJT4lIAogIHN1bW1hcmlzZSh4SVFSID0gbWVhbih4SVFSLG5hLnJtPVRSVUUpLAogICAgICAgICAgICAgICAgICAgeUlRUiA9IG1lYW4oeUlRUixuYS5ybT1UUlVFKSwKICAgICAgICAgICAgICAgICAgIHggPSBtZWFuKHhtZWQsbmEucm09VFJVRSksCiAgICAgICAgICAgICAgICAgICB5ID0gbWVhbih5bWVkLG5hLnJtPVRSVUUpKSAlPiUKICBtdXRhdGUoeSA9IHkqLTEsCiAgICAgICAgIHhtaW4gPSB4LSh4SVFSLzIpLAogICAgICAgICB4bWF4ID0geCsoeElRUi8yKSwKICAgICAgICAgeW1pbiA9IHktKHlJUVIvMiksCiAgICAgICAgIHltYXggPSB5Kyh5SVFSLzIpKQppbWcgPC0gcG5nOjpyZWFkUE5HKCJjaW5keS5wbmciKQpnIDwtIGdyaWQ6OnJhc3Rlckdyb2IoaW1nLCBpbnRlcnBvbGF0ZT1UUlVFLCB3aWR0aD11bml0KDEsIm5wYyIpLCBoZWlnaHQ9dW5pdCgxLCJucGMiKSkgCmdncGxvdChtZWRpYW5zLCBhZXMoZmlsbD1kaXJlY3Rpb24sY29sb3I9ZGlyZWN0aW9uKSkgKwogIGFubm90YXRpb25fY3VzdG9tKGcsIHhtaW49LUluZiwgeG1heD1JbmYsIHltaW49LUluZiwgeW1heD1JbmYpICsKICBnZW9tX3JlY3QoYWVzKHhtaW49eG1pbix5bWluPXltaW4seG1heD14bWF4LHltYXg9eW1heCksYWxwaGE9LjEpICsgCiAgdGhlbWVfbGluZWRyYXcoKSArCiAgc2NhbGVfeF9jb250aW51b3VzKGxpbWl0cyA9IGMoMCwxMDgwKSwgZXhwYW5kID0gYygwLCAwKSkgKwogIHNjYWxlX3lfY29udGludW91cyhsaW1pdHMgPSBjKC03MjAsMCksIGV4cGFuZCA9IGMoMCwgMCkpICsKICBmYWNldF93cmFwKCJsYW5nIikKYGBgCgojIFhZIFNwYWNlIERhdGEgLSBNdWx0aXBsZSBQbG90cwoKRmlyc3QgbGV0J3MgcHJlcCB0aGUgZGF0YS4gCmBgYHtyfQptdWx0aXBsZXMgPC0geHlkYXRhICU+JQogIGZpbHRlcighaXMubmEoeCkpICU+JQogIGZpbHRlcighaXMubmEoeSkpICU+JQogIGdyb3VwX2J5KG5hbWUsIGFnZSwgbGFuZywgc3RvcnksIGRpcmVjdGlvbiwgdHJpYWwpICU+JQogIHN1bW1hcmlzZSh4SVFSID0gSVFSKHgsbmEucm09VFJVRSksCiAgICAgICAgICAgIHlJUVIgPSBJUVIoeSxuYS5ybT1UUlVFKSwKICAgICAgICAgICAgeG1lZCA9IG1lZGlhbih4LCBuYS5ybT1UUlVFKSwKICAgICAgICAgICAgeW1lZCA9IG1lZGlhbih5LCBuYS5ybT1UUlVFKSwKICAgICAgICAgICAgYXJlYSA9IHhJUVIqeUlRUiwKICAgICAgICAgICAgeF85MCA9IHF1YW50aWxlKHgsIC45NSwgbmEucm09VFJVRSkgLSBxdWFudGlsZSh4LCAuMDUsIG5hLnJtPVRSVUUpLAogICAgICAgICAgICB5XzkwID0gcXVhbnRpbGUoeSwgLjk1LCBuYS5ybT1UUlVFKSAtIHF1YW50aWxlKHksIC4wNSwgbmEucm09VFJVRSksCiAgICAgICAgICAgIGFyZWFfOTAgPSAoeF85MCkgKiAoeV85MCksCiAgICAgICAgICAgIHhfbWVhbiA9IG1lYW4oeCwgbmEucm0gPSBUUlVFKSwKICAgICAgICAgICAgeV9tZWFuID0gbWVhbih5LCBuYS5ybSA9IFRSVUUpLAogICAgICAgICAgICB4X3NkID0gc2QoeCwgbmEucm0gPSBUUlVFKSwKICAgICAgICAgICAgeV9zZCA9IHNkKHksIG5hLnJtID0gVFJVRSksCiAgICAgICAgICAgIHhfMXNkID0gKHhfbWVhbit4X3NkKSAtICh4X21lYW4teF9zZCksCiAgICAgICAgICAgIHlfMXNkID0gKHlfbWVhbit5X3NkKSAtICh5X21lYW4teV9zZCksCiAgICAgICAgICAgIGFyZWFfMXNkID0geF8xc2QgKiB5XzFzZCwKICAgICAgICAgICAgeF8yc2QgPSAoeF9tZWFuKyh4X3NkKjIpKSAtICh4X21lYW4tKHhfc2QqMikpLAogICAgICAgICAgICB5XzJzZCA9ICh5X21lYW4rKHlfc2QqMikpIC0gKHlfbWVhbi0oeV9zZCoyKSksCiAgICAgICAgICAgIGFyZWFfMnNkID0geF8yc2QgKiB5XzJzZCkgJT4lCiAgZ3JvdXBfYnkobmFtZSwgbGFuZywgZGlyZWN0aW9uKSAlPiUKICBzdW1tYXJpc2VfaWYoaXMuZG91YmxlLCBmdW5zKG1lYW4pLCBuYS5ybSA9IFQpICU+JQogIGdyb3VwX2J5KGxhbmcsIGRpcmVjdGlvbikgJT4lCiAgc3VtbWFyaXNlX2lmKGlzLmRvdWJsZSwgZnVucyhtZWFuKSwgbmEucm0gPSBUKQoKaW1nIDwtIHBuZzo6cmVhZFBORygiY2luZHkucG5nIikKZyA8LSBncmlkOjpyYXN0ZXJHcm9iKGltZywgaW50ZXJwb2xhdGU9VFJVRSwgd2lkdGg9dW5pdCgxLCJucGMiKSwgaGVpZ2h0PXVuaXQoMSwibnBjIikpIAoKYGBgCgojIyBJUVIgKE1pZGRsZSA1MCUpCkxldCdzIHNlZS4gCmBgYHtyfQpjdXJyX2RhdGEgPC0gbXVsdGlwbGVzICU+JSAKICB1bmdyb3VwKCkgJT4lCiAgc2VsZWN0KGxhbmcsIGRpcmVjdGlvbiwgeG1lZCwgeW1lZCwgeElRUiwgeUlRUikgJT4lCiAgZ3JvdXBfYnkobGFuZywgZGlyZWN0aW9uKSAlPiUKICBzdW1tYXJpc2UoeG1pbiA9IHhtZWQtKHhJUVIvMiksCiAgICAgICAgIHhtYXggPSB4bWVkKyh4SVFSLzIpLAogICAgICAgICB5bWluID0gLTEqKHltZWQtKHlJUVIvMikpLAogICAgICAgICB5bWF4ID0gLTEqKHltZWQrKHlJUVIvMikpKQoKZ2dwbG90KGN1cnJfZGF0YSwgYWVzKGZpbGw9ZGlyZWN0aW9uLGNvbG9yPWRpcmVjdGlvbikpICsKICBhbm5vdGF0aW9uX2N1c3RvbShnLCB4bWluPS1JbmYsIHhtYXg9SW5mLCB5bWluPS1JbmYsIHltYXg9SW5mKSArCiAgZ2VvbV9yZWN0KGFlcyh4bWluPXhtaW4seW1pbj15bWluLHhtYXg9eG1heCx5bWF4PXltYXgpLGFscGhhPS4xKSArIAogIHRoZW1lX2xpbmVkcmF3KCkgKwogIHNjYWxlX3hfY29udGludW91cyhsaW1pdHMgPSBjKDAsMTA4MCksIGV4cGFuZCA9IGMoMCwgMCkpICsKICBzY2FsZV95X2NvbnRpbnVvdXMobGltaXRzID0gYygtNzIwLDApLCBleHBhbmQgPSBjKDAsIDApKSArCiAgZmFjZXRfd3JhcCgibGFuZyIpCmBgYAoKIyMgTWlkZGxlIDkwJQpTbyBJIGNhbGN1bGF0ZWQgdGhlIGF2ZXJhZ2UgbWVkaWFuIGFjcm9zcywgYW5kIHRoZSBtaWRkbGUgOTAlIG9mIHRoZSBkYXRhLiAKYGBge3J9CmN1cnJfZGF0YSA8LSBtdWx0aXBsZXMgJT4lIAogIHVuZ3JvdXAoKSAlPiUKICBzZWxlY3QobGFuZywgZGlyZWN0aW9uLCB4bWVkLCB5bWVkLCB4XzkwLCB5XzkwKSAlPiUKICBncm91cF9ieShsYW5nLCBkaXJlY3Rpb24pICU+JQogIHN1bW1hcmlzZSh4bWluID0geG1lZC0oeF85MC8yKSwKICAgICAgICAgeG1heCA9IHhtZWQrKHhfOTAvMiksCiAgICAgICAgIHltaW4gPSAtMSooeW1lZC0oeV85MC8yKSksCiAgICAgICAgIHltYXggPSAtMSooeW1lZCsoeV85MC8yKSkpCgpnZ3Bsb3QoY3Vycl9kYXRhLCBhZXMoZmlsbD1kaXJlY3Rpb24sY29sb3I9ZGlyZWN0aW9uKSkgKwogIGFubm90YXRpb25fY3VzdG9tKGcsIHhtaW49LUluZiwgeG1heD1JbmYsIHltaW49LUluZiwgeW1heD1JbmYpICsKICBnZW9tX3JlY3QoYWVzKHhtaW49eG1pbix5bWluPXltaW4seG1heD14bWF4LHltYXg9eW1heCksYWxwaGE9LjEpICsgCiAgdGhlbWVfbGluZWRyYXcoKSArCiAgc2NhbGVfeF9jb250aW51b3VzKGxpbWl0cyA9IGMoMCwxMDgwKSwgZXhwYW5kID0gYygwLCAwKSkgKwogIHNjYWxlX3lfY29udGludW91cyhsaW1pdHMgPSBjKC03MjAsMCksIGV4cGFuZCA9IGMoMCwgMCkpICsKICBmYWNldF93cmFwKCJsYW5nIikKCiMgZ2dwbG90KGZpbHRlcihjdXJyX2RhdGEsIGxhbmcgPT0gIk5TRSIpLCBhZXMoZmlsbD1kaXJlY3Rpb24sY29sb3I9ZGlyZWN0aW9uKSkgKwojICAgYW5ub3RhdGlvbl9jdXN0b20oZywgeG1pbj0tSW5mLCB4bWF4PUluZiwgeW1pbj0tSW5mLCB5bWF4PUluZikgKwojICAgZ2VvbV9yZWN0KGFlcyh4bWluPXhtaW4seW1pbj15bWluLHhtYXg9eG1heCx5bWF4PXltYXgpLGFscGhhPS4yLCBzaXplID0gMSkgKwojICAgdGhlbWVfbGluZWRyYXcoKSArCiMgICBzY2FsZV94X2NvbnRpbnVvdXMobGltaXRzID0gYygwLDEwODApLCBleHBhbmQgPSBjKDAsIDApKSArCiMgICBzY2FsZV95X2NvbnRpbnVvdXMobGltaXRzID0gYygtNzIwLDApLCBleHBhbmQgPSBjKDAsIDApKQojIAojIAojIGdncGxvdChmaWx0ZXIoY3Vycl9kYXRhLCBsYW5nID09ICJTRSIpLCBhZXMoZmlsbD1kaXJlY3Rpb24sY29sb3I9ZGlyZWN0aW9uKSkgKwojICAgYW5ub3RhdGlvbl9jdXN0b20oZywgeG1pbj0tSW5mLCB4bWF4PUluZiwgeW1pbj0tSW5mLCB5bWF4PUluZikgKwojICAgZ2VvbV9yZWN0KGFlcyh4bWluPXhtaW4seW1pbj15bWluLHhtYXg9eG1heCx5bWF4PXltYXgpLGFscGhhPS4yLCBzaXplID0gMSkgKwojICAgdGhlbWVfbGluZWRyYXcoKSArCiMgICBzY2FsZV94X2NvbnRpbnVvdXMobGltaXRzID0gYygwLDEwODApLCBleHBhbmQgPSBjKDAsIDApKSArCiMgICBzY2FsZV95X2NvbnRpbnVvdXMobGltaXRzID0gYygtNzIwLDApLCBleHBhbmQgPSBjKDAsIDApKQpgYGAKCiMjIMKxMSBTRCAoTWlkZGxlIDY4JSkKU28gdGhpcyBpcyB1c2luZyB0aGUgbWVhbiBvZiB0aGUgbWVhbnMsIHBsdXMgb3IgbWludXMgb25lIFNELiAgVGhpcyBpcyBlcXVpdmFsZW50IHRvIG1pZGRsZSA2OCUuIApgYGB7cn0KY3Vycl9kYXRhIDwtIG11bHRpcGxlcyAlPiUgCiAgdW5ncm91cCgpICU+JQogIHNlbGVjdChsYW5nLCBkaXJlY3Rpb24sIHhfbWVhbiwgeV9tZWFuLCB4XzFzZCwgeV8xc2QpICU+JQogIGdyb3VwX2J5KGxhbmcsIGRpcmVjdGlvbikgJT4lCiAgc3VtbWFyaXNlKHhtaW4gPSB4X21lYW4tKHhfMXNkLzIpLAogICAgICAgICB4bWF4ID0geF9tZWFuKyh4XzFzZC8yKSwKICAgICAgICAgeW1pbiA9IC0xKih5X21lYW4tKHlfMXNkLzIpKSwKICAgICAgICAgeW1heCA9IC0xKih5X21lYW4rKHlfMXNkLzIpKSkKCmdncGxvdChjdXJyX2RhdGEsIGFlcyhmaWxsPWRpcmVjdGlvbixjb2xvcj1kaXJlY3Rpb24pKSArCiAgYW5ub3RhdGlvbl9jdXN0b20oZywgeG1pbj0tSW5mLCB4bWF4PUluZiwgeW1pbj0tSW5mLCB5bWF4PUluZikgKwogIGdlb21fcmVjdChhZXMoeG1pbj14bWluLHltaW49eW1pbix4bWF4PXhtYXgseW1heD15bWF4KSxhbHBoYT0uMSkgKyAKICB0aGVtZV9saW5lZHJhdygpICsKICBzY2FsZV94X2NvbnRpbnVvdXMobGltaXRzID0gYygwLDEwODApLCBleHBhbmQgPSBjKDAsIDApKSArCiAgc2NhbGVfeV9jb250aW51b3VzKGxpbWl0cyA9IGMoLTcyMCwwKSwgZXhwYW5kID0gYygwLCAwKSkgKwogIGZhY2V0X3dyYXAoImxhbmciKQpgYGAKCiMjIMKxMiBTRCAoTWlkZGxlIDk2JSkKQW5kIHRoaXMgaXMgdXNpbmcgdGhlIG1lYW4gb2YgdGhlIG1lYW5zLCBwbHVzIG9yIG1pbnVzIHR3byBTRC4gIFRoaXMgaXMgZXF1aXZhbGVudCB0byBtaWRkbGUgOTYlLiAKYGBge3J9CmN1cnJfZGF0YSA8LSBtdWx0aXBsZXMgJT4lIAogIHVuZ3JvdXAoKSAlPiUKICBzZWxlY3QobGFuZywgZGlyZWN0aW9uLCB4X21lYW4sIHlfbWVhbiwgeF8yc2QsIHlfMnNkKSAlPiUKICBncm91cF9ieShsYW5nLCBkaXJlY3Rpb24pICU+JQogIHN1bW1hcmlzZSh4bWluID0geF9tZWFuLSh4XzJzZC8yKSwKICAgICAgICAgeG1heCA9IHhfbWVhbisoeF8yc2QvMiksCiAgICAgICAgIHltaW4gPSAtMSooeV9tZWFuLSh5XzJzZC8yKSksCiAgICAgICAgIHltYXggPSAtMSooeV9tZWFuKyh5XzJzZC8yKSkpCgpnZ3Bsb3QoY3Vycl9kYXRhLCBhZXMoZmlsbD1kaXJlY3Rpb24sY29sb3I9ZGlyZWN0aW9uKSkgKwogIGFubm90YXRpb25fY3VzdG9tKGcsIHhtaW49LUluZiwgeG1heD1JbmYsIHltaW49LUluZiwgeW1heD1JbmYpICsKICBnZW9tX3JlY3QoYWVzKHhtaW49eG1pbix5bWluPXltaW4seG1heD14bWF4LHltYXg9eW1heCksYWxwaGE9LjEpICsgCiAgdGhlbWVfbGluZWRyYXcoKSArCiAgc2NhbGVfeF9jb250aW51b3VzKGxpbWl0cyA9IGMoMCwxMDgwKSwgZXhwYW5kID0gYygwLCAwKSkgKwogIHNjYWxlX3lfY29udGludW91cyhsaW1pdHMgPSBjKC03MjAsMCksIGV4cGFuZCA9IGMoMCwgMCkpICsKICBmYWNldF93cmFwKCJsYW5nIikKYGBg